How do I determine if Windows Credentials are disabled - security

I am using the CredRead() and CredWrite() functions from the Windows Credential Manager API to store and retrieve user passwords, as outlined in this StackOverflow answer.
However, I have read that it is possible to disable the Credential Manager by setting a Group Policy, or simply by stopping/disabling the Credential Manager service. In this case, I would like to update my application's UI to reflect that Credential storage is not currently available.
Is there a reliable way to determine programmably whether or not the Credential Manager has been disabled?

in windows exist VaultSvc (friendly name Credentials Service) which support different vault types. exist util VaultCmd.exe with which we can enumerate different credential schemas and loaded vaults. for example:
vaultcmd /listschema
Global Schemas
Credential schema: Windows Secure Note
Schema guid: 2F1A6504-0641-44CF-8BB5-3612D865F2E5
Credential schema: Windows Web Password Credential
Schema guid: 3CCD5499-87A8-4B10-A215-608888DD3B55
Credential schema: Windows Credential Picker Protector
Schema guid: 154E23D0-C644-4E6F-8CE6-5069272F999F
Currently loaded credentials schemas:
Vault: Web Credentials
Vault Guid:4BF4C442-9B8A-41A0-B380-DD4A704DDB28
Credential schema: Windows Web Password Credential
Schema guid: 3CCD5499-87A8-4B10-A215-608888DD3B55
Vault: Windows Credentials
Vault Guid:77BC582B-F0A6-4E15-4E80-61736B6F3B29
Credential schema: Windows Domain Certificate Credential
Schema guid: E69D7838-91B5-4FC9-89D5-230D4D4CC2BC
Credential schema: Windows Domain Password Credential
Schema guid: 3E0E35BE-1B77-43E7-B873-AED901B6275B
Credential schema: Windows Extended Credential
Schema guid: 3C886FF3-2669-4AA2-A8FB-3F6759A77548
and
vaultcmd /list
Currently loaded vaults:
Vault: Web Credentials
Vault Guid:4BF4C442-9B8A-41A0-B380-DD4A704DDB28
Location: C:\Users\*\AppData\Local\Microsoft\Vault\4BF4C442-9B8A-41A0-B380-DD4A704DDB28
Vault: Windows Credentials
Vault Guid:77BC582B-F0A6-4E15-4E80-61736B6F3B29
Location: C:\Users\*\AppData\Local\Microsoft\Vault
of course vaultcmd and most vaults, say Web Credentials (store passwords in ie) will be work only in case VaultSvc is running
but Windows Credentials (77BC582B-F0A6-4E15-4E80-61736B6F3B29) is built in credential, which is always running (inside lsass), even if VaultSvc not running (disabled). the CredRead, CredWrite, CredEnumerate, and other Cred* api will be always work. it can not be disabled
exist undocumented api Vault* api implemented in vaultcli.dll. all this api named in form Vault*. when we call it and in case VaultSvc is running - vaultsvc.dll is loaded in lsass and handled remote call :
vaultcli!VaultSomeApi -> rpc - > vaultsvc!VltSomeApi
for example when we call VaultEnumerateItems in client, VltEnumerateItems called in lsass (vaultsvc.dll). what is internally called inside VltEnumerateItems depend from concrete vault, on which it called. for Windows Credentials vault - CredEnumerateW called inside VltEnumerateItems

The name of the Credentials Service is VaultSvc.
You can find how to query the status of any service in this answer and just use the code whilst passing the "ValutSvc" string to the function.

Related

How to ask DefaultAzureCredential to use my user credential locally

I'm trying to develop a web app on an Azure VM that uses Azure Key Vault. Later this app will also be deployed to Azure. As far as I know, the most straight forward way to make the app work, both locally and deployed, with the key vault, is to use the DefaultAzureCredential class. The code would be like this:
string kvUri = "https://" + keyvaultName + ".vault.azure.net";
SecretClient client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
KeyVaultSecret secret = await client.GetSecretAsync(secretName);
At runtime, the provider will try different credential types in order.
This sounds exactly what I want:
When developing locally (on the Azure VM, though), I want to use my user credential (user identity added to the key vault's permission) without any configuration, since I have already logged into the Visual Studio using the same user credential.
Once deployed to Azure, I want to use the app registration credential (also added to the key vault's permission).
But when running the app locally, I'm getting a 403 error The user, group or application .... does not have secrets get permission on key vault ...
After looking up the object id in the error message, I realize it's the dev machine Azure VM's credential that the application uses, not my user credential.
Is there a way to change this behavior?
To prevent the Azure VM from getting a token, you can exclude the ManagedIdentityCredential in your Development environment and only enable it in a Non-Development environment.
if (environment.IsDevelopment())
{
var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ExcludeManagedIdentityCredential = true,
ExcludeAzureCliCredential = true
});
}
else
{
var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true
});
}
Once deployed to Azure, I want to use the app registration credential (also added to the key vault's permission).
An Azure App Service can use a managed identity as well. There is no need for a separate App Registration.
See https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme#key-concepts for more information.
Create and identity if you wish to use (default identity)
appservice -> select you application -> identity->enable it ->should give you a Id
and than add it to key Vault Access policy
alternatively app registration can be used with tenantId,clientId,secret to connect to keyvault

Microsoft Graph permissions issue when using managed identity and DefaultAzureCredential

I have set up a test project that follows this microsoft guide: https://learn.microsoft.com/en-us/azure/app-service/scenario-secure-app-access-microsoft-graph-as-app?tabs=azure-powershell
The only difference that I made from that tutorial is the code portion. I changed it to look like this:
TokenCredential tokenCredential = new DefaultAzureCredential();
var scopes = new[] { "https://graph.microsoft.com/.default" };
var graphClient = new GraphServiceClient(tokenCredential, scopes);
var group = graphClient.Groups["<my-group-id>"].Request().GetAsync().Result;
Everything works as expected when I publish the website and access it, but when I run this code locally I receive
Insufficient privileges to complete the operation.
I am signed into VS using the same account that I am using in Azure portal (it's a global admin account). Is there any other configuration setting that I am missing so that I can run this code and test locally?
Usually you need one of the following permissions to query groups i.e delegated and application permissions : GroupMember.Read.All, Group.Read.All, Directory.Read.All, Group.ReadWrite.All, Directory.ReadWrite.All User.Read.All
Run VS as administrator and also give user administrator role.
But visual studio may not work in this case . So please try with
different credential type like client secret/certificate credential
with your app .
In local debugging ,use Shared Token Cache Credential ,as in
your local environment, DefaultAzureCredential uses the shared token
credential from the IDE.
In Visual Studio, you can set the account that you want to use when
debugging using VS : under Options -> Azure Service Authentication.
Please check Azure Managed Service Identity And Local Development by Rahul Nath (rahulpnath.com)
If multiple accounts are configured, try to set the SharedTokenCacheUsername property to that specific account to use.
var azureCredentialOptions = new DefaultAzureCredentialOptions();
azureCredentialOptions.SharedTokenCacheUsername = "<azure ad User Name>";
var credential = new DefaultAzureCredential(azureCredentialOptions);
Reference: DefaultAzureCredential: Unifying How We Get Azure AD Token | Rahul Nath (rahulpnath.com)

Hide OracleDatabase credentials in Node.js

I'm connecting to an external Oracle Database with the example function that can be found here
const oracledb = require('oracledb');
const connection = await oracledb.getConnection(
{
user : "hr",
password : mypw, // mypw contains the hr schema password
connectString : "mydbmachine.example.com/orclpdb1"
}
);
So, as you can see, my credentials would be 'exposed' to everyone who can access the code (maybe github repository or something).
Is there any way of hiding my username and password or making them confidential, or I just shouldn't worry about it?
Note: I'm using the oracledb node module
You could use .env, and access to it with process.env.
check here: https://nodejs.org/dist/latest-v8.x/docs/api/process.html#process_process_env
Store your database secrets encrypted in Secrets Manager or Parameter Store and have your app read them at runtime. Be sure to update the IAM role that your app uses so that it has IAM permissions to retrieve the credentials.
Note: for certain databases, Secrets Manager supports auto-rotation of credentials.
Choices include:
prompt for the password at runtime
pass the password in an environment variable
use kerberos and then use 'external' authentication in node-oracledb. All this is configured and enabled in code layers below node-oracledb, see the Oracle Database Security Guide.
use an Oracle Wallet and then use 'external' authentication in node-oracledb.

"Caller does not have permission" trying to create custom token with Firebase Admin SDK

Error
When calling admin.auth().createCustomToken() I am getting the following error:
Error: The caller does not have permission; Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature.
The provided documentation leads me to believe that the service account I am initializing the Firebase Admin SDK with does not have sufficient permissions. I don't believe this to be the case, so I want to ask and see if I've missed anything.
Configuration
Firebase Admin SDK is initialized in the backend like so:
admin.initializeApp({
serviceAccountId: 'firebase-adminsdk-xxxxx#my-project-id.iam.gserviceaccount.com'
});
Technically the value is referenced from an env var, but I have confirmed this value to be correct.
The service account being used has the following roles:
roles/firebase.sdkAdminServiceAgent
roles/iam.serviceAccountTokenCreator
Per the documentation, the required permission for creating custom tokens is iam.serviceAccounts.signBlob. This permission is part of the iam.serviceAccountTokenCreator role as per this output:
❯ gcloud beta iam roles describe roles/iam.serviceAccountTokenCreator
description: Impersonate service accounts (create OAuth2 access tokens, sign blobs
or JWTs, etc).
etag: AA==
includedPermissions:
- iam.serviceAccounts.get
- iam.serviceAccounts.getAccessToken
- iam.serviceAccounts.getOpenIdToken
- iam.serviceAccounts.implicitDelegation
- iam.serviceAccounts.list
- iam.serviceAccounts.signBlob
- iam.serviceAccounts.signJwt
- resourcemanager.projects.get
- resourcemanager.projects.list
name: roles/iam.serviceAccountTokenCreator
stage: GA
title: Service Account Token Creator
Lastly, the code in question that is erroring out is as follows:
try {
const loginToken = await admin.auth().createCustomToken(uid);
return response(200).json({ loginToken });
} catch (err) {
...
}
The uid comes from signing in a user via a GoogleUser credential - the provided uid is confirmed to be accurate, and this flow works locally when referencing a JSON key file for the same service account.
Server is running on GKE, in case it could be a cluster permission error.
Any help would be greatly appreciated!
EDIT - RESOLVED
Hiranya's answer did the trick - the K8s deployment had been configured with a service account whose original intent was only to enable Cloud SQL Proxy. Giving this service account the serviceAccountTokenCreator role solved the issue.
You need to make sure the service account that the SDK is authorized with (not the one specified as serviceAccountId) has the token creator role. This is the service account auto-discovered by Google Application Default Credentials. In case of Cloud Functions this is the service account named {project-name}#appspot.gserviceaccount.com. You need to figure out the equivalent service account for GKE and grant it the token creator role.

Use a certificate in the keyvault to access multi-tenant application in other tenant

We have a multi-tenant application in our Azure AD tenant. It is authorized in some other tenants (we know which ones). And it has multiple certificates registered to it to be used as client credentials.
We want to remove the certificates from the local stores and use a certificate in the key vault to request a token for one of the external tenant. According to the documentation this is one of the use cases.
Our tenant (id: xxxx):
Has app registration (app id: abcd-xxx-xxxx-xxx)
has keyvault
has managed service principal (with access to the key vault)
other tenant (id: yyyy):
Executed Admin consent for our application.
Question 1:
How do I create a certificate in the Key vault that is connected to an existing application (app id: abcd-xxx-xxxx-xxx)? It is important to note that since the application is already approved by several third party admins, it cannot be recreated. Same counts for creating a new certificate after it would be expired.
Question 2:
How to I setup the Microsoft.Azure.Services.AppAuthentication library to:
Use the managed identity to access the key vault in our tenant (xxxx).
Use the certificate in the key vault to request a token for our app (abcd-xxx-xxxx-xxx) in other companies tenant (yyyy)
Answer 1:
You could use az ad sp credential reset command like below. If you don't want to overwrite the existing certificate of the App, please pass the --append parameter.
az ad sp credential reset --name '<application-id>' --keyvault joykeyvault --cert cer136 --create-cert --append
Answer 2:
1.To use the MSI access the keyvault in your tenant, just use the code below.
No code changes are required, when you run your code on an Azure App Service or an Azure VM with a managed identity enabled, the library automatically uses the managed identity, see this link.
The environment variable AzureServicesAuthConnectionString has to be set to any credential with access to the keyvault. RunAs=Developer; DeveloperTool=AzureCli for dev or RunAs=App; for managed service identity (automatically in azure).
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
// Instantiate a new KeyVaultClient object, with an access token to Key Vault
var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
2.If you want to use the service principal along with its certificate stored in the keyvault to get the token for the resources in another tenant, the connection string on the AzureServiceTokenProvider has to be set to RunAs=App;AppId={TestAppId};KeyVaultCertificateSecretIdentifier={KeyVaultCertificateSecretIdentifier} then you can get tokens for other tenants like.
const string appWithCertConnection = "RunAs=App;AppId={TestAppId};KeyVaultCertificateSecretIdentifier=https://myKeyVault.vault.azure.net/secrets/myCert";
Then use the code to get the token, e.g. for the resource https://management.azure.com/.
var azureServiceTokenProvider2 = new AzureServiceTokenProvider(appWithCertConnection);
string accessToken = await azureServiceTokenProvider2.GetAccessTokenAsync("https://management.azure.com/", "tenant-id-of-thridh-party-tenant").ConfigureAwait(false);

Resources