Can you use C# Kubernetes inClusterConfig for a remote Cluster? - c#

I am having trouble authenticating my C# service for a remote cluster. Trying to use my svc gets Forbidden, so I am hoping to work around with this. I know that inClusterConfig does work properly when this service is in the Cluster, but I am trying to run local and host jobs in my remote cluster.
This is what I am trying:
Environment.SetEnvironmentVariable("KUBERNETES_SERVICE_HOST", "Value1");
Environment.SetEnvironmentVariable("KUBERNETES_SERVICE_PORT", "Value1");
KubernetesClientConfiguration config = new KubernetesClientConfiguration();
config.Host = "https://xx";
config = KubernetesClientConfiguration.InClusterConfig();
Not sure if this is possible. Currently getting error
Unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
Thanks

In addition to the environment variables, KubernetesClientConfiguration.IsInCluster also requires a token and certificate:
if (!FileUtils.FileSystem().File.Exists(tokenPath))
{
return false;
}
// ...
return FileUtils.FileSystem().File.Exists(certPath);
The details of authentication are explained in this answer:
When accessing the API from a Pod, the client certificate is located
on /var/run/secrets/kubernetes.io/serviceaccount/ca.crt and in
addition, you need to authenticate using the token located on
/var/run/secrets/kubernetes.io/serviceaccount/token
Once a connection is being attempted, per this answer:
InClusterConfig uses the default service account of the namespace
where you are deploying the pod. By default that service account will
not have any RBAC which leads to Forbidden error.

Related

Error C# Dynamics CRM: The authentication endpoint Username was not found on the configured Secure Token Service

We're facing an error while trying to deploy a WCF webservice in a server. While connecting to Dynamics (CRM on premise) we get this error: The authentication endpoint Username was not found on the configured Secure Token Service
If we test it locally, it's working but if the deploy the webservice in the server, this is the code which performs the login:
Uri serviceUri = new Uri(OrgServiceUri);
proxy = new OrganizationServiceProxy(serviceUri, null, authCredentials, null);
proxy.EnableProxyTypes();
_service = (IOrganizationService)proxy;
Guid userid = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).UserId;
if (userid != Guid.Empty)
{
Console.WriteLine(userid);
return true;
}
else
{
return false;
}
Any guess?
Thank you!!
First, make sure the user you have set up as the service account has Read/Write access to CRM and has a security role assigned that enables it to log into CRM remotely.
Next, make sure the Username endpoint is configured in the ADFS deployment that this CRM org is using:
Log onto the ADFS server and open the ADFS management console. Go to ADFS > Service > Endpoints
You’ll see a list of endpoint URLs here. Find the one for /adfs/services/trust/13/username of type WS-Trust 1.3
Make sure that this endpoint has “Yes” set for both the Enabled and Proxy Enabled settings.
If you have to make a change to this endpoint, after making the change re-start the ADFS server and the CRM server, then try to register again.
Lastly, if the above looks okay, it could be a resolution or routing issue blocking the connection. Make sure that there are external DNS entries for the path to your ADFS server. Also, make sure that your firewall permits external access to the ADFS server. If you are able to, try to use a computer that is outside of your domain to navigate directly to the ADFS server to test its accessibility.
This is a problem with the same error as you, and it has been resolved, you can refer to: The authentication endpoint Username was not found on the configured Secure Token Service
Finally we found it was an issue with ADFS service per-se, networking related, since it wasnt able to connect SSO site. After fixing that, it started to work as a charm.
If you are running ADFS on-prem, the ADFS windows service might be stopped (Because of a power failure / unexpected server restart).
You just need to start it.

Token access blocked when posting request from published Azure function

I am struggling to get a token from "https://login.microsoftonline.com/common/oauth2/token" with an Azure function by a post-request. The token will give permissions to access SharePoint though CSOM. Here is my code snippet with the post request:
var clientId = defaultAADAppId;
var body = $"resource={resource}&client_id={clientId}&grant_type=password&username={HttpUtility.UrlEncode(username)}&password={HttpUtility.UrlEncode(password)}";
using (var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded"))
{
var result = await httpClient.PostAsync(tokenEndpoint, stringContent);
var tokenResult = JsonSerializer.Deserialize<JsonElement>(result);
var token = tokenResult.GetProperty("access_token").GetString();
}
When testing locally, both when running the function in Visual studio and when I try with Postman, I am able to achieve an access token. However, as soon as I publish the function to my Function app in Azure I receive the following error message:
"AADSTS53003: Access has been blocked by Conditional Access policies. The access policy does not allow token issuance"
I have enabled an app registration in the portal and as mentioned, it all works fine until I publish everything to Azure.
Any ideas on how to solve this?
I got it to work now. First of all I reviewed the CA policies as #CaseyCrookston suggested. What I found out was that our CA policies blocked calls outside the country we operate from. However, the calls from the App registration/Azure function were registered from the Azure data centre location and thus, blocked by our CA policies. When running them locally the calls where registered in my country and therefore no errors were showing while debugging.
My first step was trying to add my Client app to the CA policy, which was not possible. The client/secret authentication that I used based on the suggestions in this CSOM guide by Microsoft prevented the App registration to be whitelisted from the CA policies (Github issue).
Based on this I had to change the authentication to a Certificate-based authentication as suggested here: Access token request with a certificate and here: SO answer. With this I was able to whitelist the App registration in the CA policies and successfully authenticate to the Sharepoint CSOM.
As the error message says, your app is blocked by CA policy. Possible causes can be unknown client app, blocking external IP addresses, etc.
You can perform one of the below workarounds:
Add your Client app to your CA policy.
I wouldn’t recommend this because this affects your security - if you take the risk you could exclude the “Microsoft Azure Management” from your CA policy which blocks unknown clients / requires device state and still protect the sign-in with MFA.
A better approach is to use another OAuth 2.0 and OpenID connect flow like the delegated flow where you sign-in directly within the app, if possible.

Does Connecting to Remote WMI from an ASP.NET Page using Constrained Delegation Require Protocol Transition?

I'm working on an older web app that I did not originally build, but now maintain. It is a classic ASP app with ASPX pages mixed in.
The site is setup for Kerberos authentication and delegation, and that is working properly to other boxes (e.g. I can run a SQL query against a back-end server from an ASP page in the site and it connects using the front-end client's credentials properly). So SPNs are registered, delegation privileges are configured in AD, etc.
Now, the part I'm having trouble with is an ASPX page which invokes a remote WMI call to check on the status of an IIS website, using the \root\WebAdministration WMI namespace. The ASPX page is itself invoked by way of an XHR which resides in the client-side code of a different ASP page. The ASPX, when invoked, makes the WMI call, then Response.Write's back the necessary data, which the originating ASP page then utilizes to populate the page that the user sees. The problem is, I cannot get the IIS box to properly delegate the user's credentials to the back-end machine that its making the WMI call against.
This all works properly (including the constrained delegation), but only if I enable protocol transition. If I set the delegation on the middle-tier (IIS) box to use only Kerberos authentication, it fails (I get an anonymous logon attempt on the back-end box).
Now, I've done numerous packet captures on both the front-end client and the IIS box to see exactly what is going on here, and I can see several things:
The front-end client is properly getting its Kerberos ticket, and presenting it to the IIS box for authentication.
The IIS box is accepting the Kerberos ticket from the client.
However, the IIS box is not using the ticket received from the client as the "evidence ticket" that it should be presenting to the KDC in order to obtain a service ticket to access the back-end service on behalf of the front-end user. Instead, the IIS box is using a S4U2Self call to the KDC to obtain a ticket on the front-end user's behalf for itself, then using that ticket in the subsequent S4U2Proxy call to try and obtain the ticket to the back-end. This is where the problem lies.
The behavior noted above is why this works when protocol transition is enabled, and does not work when it is not.
I cannot figure out for the life of me, why the IIS box feels the need to obtain a TGS for itself to use as the "evidence ticket" to get the ticket for accessing the back-end, instead of simply using the ticket presented by the client. There is nothing invalid about the client's ticket from what I can tell, and the client is establishing a Kerberos-authenticated connection with the web server just fine, so there should be no need for protocol transition here. I could enable it if really needed, but I really just want to know why its necessary (if there is valid reason and this is by design then so be it).
The IIS app pool is running as the built-in app pool identity, and the delegation settings are thus configured on the IIS machine account in AD. SPNs are registered for the site against the IIS machine account, and for the back-end services against those service and/or machine accounts, and the "allowedToDelegateTo" list is configured on the IIS machine account, allowing constrained delegation to the necessary services. The specific SPN we are trying to delegate creds to in this scenario is RPCSS/[machine] for the WMI call. I've verified via the packet capture that the SPN in the request matches the SPN in the A2D2 list exactly (of course, if it didn't, then it wouldn't be working when protocol transition was enabled anyway).
As for the actual WMI connection code, I've tried a few ways. One was something like this:
ConnectionOptions co = new ConnectionOptions();
// I did try ImpersonationLevel set to both Impersonate and Delegate, but I don't think I need
// Delegate here because I'm not delegating from the remote WMI machine to a different box; instead,
// I'm delegating from the IIS box to the remote WMI machine.
co.Impersonation = ImpersonationLevel.Impersonate;
co.Authentication = AuthenticationLevel.PacketPrivacy;
co.EnablePrivileges = true;
// Tried this for the Authority line because I noticed in the packet captures that the principal
// specified here becomes the SPN that is used in the S4U2Proxy request.
co.Authority = "kerberos:RPCSS/machine.domain.com";
ManagementScope ms = new ManagementScope(#"\\machine.domain.com\root\WebAdministration", co);
Then I also tried this:
ConnectionOptions co = new ConnectionOptions();
co.Impersonation = ImpersonationLevel.Impersonate;
co.Authentication = AuthenticationLevel.PacketPrivacy;
co.EnablePrivileges = true;
// I also tried this for the Authority line based on various other code examples for similar
// issues, but this resulted in an incorrect SPN being used in the request.
co.Authority = #"kerberos:DOMAIN\machine";
ManagementScope ms = new ManagementScope(#"\\machine.domain.com\root\WebAdministration", co);
I also tried the same as above, but without an Authority line, and the correct SPN was used in the request but it still didn't work.
Finally, I also tried this, with no ConnectionOptions object at all, hoping it would just pass on the default creds:
ManagementScope ms = new ManagementScope(#"\\machine.domain.com\root\WebAdministration");
Any help here on either how I can get this working without enabling protocol transition, or info on why this setup would require protocol transition, would be very much appreciated!

My AzureAD - registered application doesn't have the rights to do anything ...?

I'm writing a c# program right now that tries to authenticate with Azure to make a generic http request. I finally got the code working and I wanted to test the features but for every request I make I get the following error code in response:
{"error":{"code": "AuthorizationFailed", "message":"The client "(id of the app I registered in AzureAD)" with object id "(same value as before)" does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/read' over scope '/subscriptions/(mysubscriptionid)'."}}.
The thing is ... The account I use to set everything up is a global admin. I checked every permission box in AzureAD I could find...
(that's 8 Application Permissions and 9 Delegated permissions in the Windows Azure Active Directory API and 1 delegated Permission in the Windows Azure Service Management API, though I don't know why there aren't more possible permissions for Azure Service Management)
the relevant code is rather basic but it works so I don't feel like I need post it, I'll just say that I obtain the Token using Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenAsync() with
authorityUri = "https://login.windows.net/(mytenantid)",
string resourceUri = "https://management.azure.com/";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
var res = authContext.AcquireTokenAsync(resourceUri, new
ClientCredential(clientId,clientSecret));
return res.Result;
and make the Request to
https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2016-03-01&$filter=atScope()
(as an example, this one is supposed to call the roles).
Tried several different types of GET Requests to different URIs, all give similar errors.
I'm thinking it might not be an issue with the code but a setting in the AzurePortal but everything I found there seems set up right (or rather "universal access").
According to your description, you forget to grant your service principal. You could add it on Azure Portal. You could grant Contributor or Owner role to it.
Please refer to this link:Assign application to role.

WCF same Identity as on client?

For an experimenting project I'am struggling with a service. The client is an ASP.NET MVC 4 and the service will be build with WCF. For now all the systems are in a trusted subsystem so SSL/certificates is not necessarily.
The problem I'am currently dealing with is: Is het possible when I create a new GenericIdentity like:
IIdentity newIdentity = new GenericIdentity("Test", "Custom authentication");
string[] newRoles = { "TestRole" };
IPrincipal testPrincipal = new GenericPrincipal(newIdentity, newRoles);
Thread.CurrentPrincipal = testPrincipal;
It is possible to have the created user when I'am on the WCF service calling the following code:
ServiceSecurityContext.Current.WindowsIdentity;
Or
ServiceSecurityContext.Current.PrimaryIdentity;
Or
Thread.CurrentPrinicpal;
I get the user which I created in the client? Or do I have to write a WCF extensibility for this?
I'm currently using a WsHttpBinding and security mode Transport and clientCredentialType: Windows. Maybe something wrong about the configuration?
On server side (WCF), the security context will have the username value you have used to authenticate to the service.
This means, that if you have defined on client side windows authentication, WCF will find the security context filled with the username of the windows identity you used.
In order for you to authenticate to the servive with windows account, you can use the following code
on client side :
channelFactory.Credentials.Windows.ClientCredential =
new NetworkCredential(username, password, domain);
Having used this code, you can access the identity on server side with the below code :
OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
In general, try to be explicit on client side authentication info. Currently, you seem to
be simply using the default behavior of windows authentication schema, by setting identity
on current thread.
I hope this helps.
I discovered to achieve this automatically in WCF that you must specify a certificate...
In the messages that are sent to the WCF service I created a few properties with the information in the datacontracts that is necessary to create a GenericPrinicpal (in this the username en the roles). Because I have an trusted subsystem I don't want to authenticate the user on each WCF-service (to much overhead for my scenario). See also Trusted subsystem
With this I created a WCF extension that implemented a parameter inspector and with reflection I set the credentials from the CurrentPrincipal in the specified properties of the contract. For more information about parameter inspectors and how to apply it

Categories