Assign App Service - Identity to KeyVault in Azure using Pulumi - c#

I create an App Service using "classic" Pulumi.Azure:
var appservice=new AppService(appserviceName, new AppServiceArgs
{
Name = appserviceName,
Location = _resourceGroup.Location,
AppServicePlanId = _servicePlan.Id,
ResourceGroupName = _resourceGroup.Name,
SiteConfig = new Pulumi.Azure.AppService.Inputs.AppServiceSiteConfigArgs
{
DotnetFrameworkVersion = "v5.0",
ScmType = "None",
},
Tags = { { "environemnt", "dev" } },
Logs = new AppServiceLogsArgs
{
HttpLogs = new AppServiceLogsHttpLogsArgs
{
FileSystem = new AppServiceLogsHttpLogsFileSystemArgs { RetentionInDays = 14, RetentionInMb = 35 }
}
}
,
AppSettings = appSettings
});
I also create a keyvault:
var currentConfig=Output.Create(GetClientConfig.InvokeAsync());
var keyVault = new KeyVault(vaultname, new KeyVaultArgs
{
Name = vaultname,
Location = _resourceGroup.Location,
ResourceGroupName = _resourceGroup.Name,
TenantId = currentConfig.Apply(q => q.TenantId),
SkuName="standard"
, AccessPolicies=
{
new Pulumi.Azure.KeyVault.Inputs.KeyVaultAccessPolicyArgs
{
TenantId=currentConfig.Apply(q=>q.TenantId),
ObjectId=currentConfig.Apply(q=>q.ObjectId),
KeyPermissions={"get", "create", "list"},
SecretPermissions={"set","get","delete","purge","recover", "list"}
}
}
});
Both work as expected. KeyVault and App Service are being created and accessable by me. Now I need that the App Service also can access the KeyVault.
But when adding a new Access Policy I am stuck at the ObjectId. The App Service does not seem to have a valid object id I can assign to the vault. When checking the service on Azure Portal I also see the Identy is missing:
So what has to be done as pulumi code that would achieve the same thing as clicking onto "On" in Azure and retrieve the ObjectId afterwards?

You need to set the following property on AppService to enable the managed identity:
Identity = new AppServiceIdentityArgs {Type = "SystemAssigned"},
This example illustrates the end-to-end implementation: https://github.com/pulumi/examples/blob/327afe30ce820901f210ed2a01da408071598ed6/azure-cs-msi-keyvault-rbac/AppStack.cs#L128

Related

How to create a API scope using Azure AD Graph API

I'm trying to use the Azure AD Graph API to create an API Scope for an Azure AD B2C application. This is the operation performed using the "Expose an API" blade in the portal.
I've tried adding the scope directly to the application like so:
var current = await graphClient.Applications[appId].Request().GetAsync();
var currentList = current.Api.Oauth2PermissionScopes ?? new List<PermissionScope>();
var newScope = new PermissionScope
{
AdminConsentDescription = scopeDescription,
AdminConsentDisplayName = scopeDescription,
IsEnabled = true,
Type = "Admin",
Value = scopeName
};
var updated = new Application {
Api = new ApiApplication {
Oauth2PermissionScopes = currentList.Append(newScope).ToList()
}
};
await graphClient.Applications[appId].Request().UpdateAsync(updated);
However, when I do that, I get an exception:
Microsoft.Graph.ServiceException
Code: ValueRequired
Message: Property api.oauth2PermissionScopes.id value is required but is empty or missing.
Does this mean that I need to create the scope separately then add it to the application? Looking over the Graph API docs, it isn't obvious how to do that and I haven't found any articles that discuss it, either.
How do you use Graph API to create API scopes?
if you want to use the Microsoft Graph API to create an API Scope for an Azure AD B2C application, we need to define PermissionScope object. The object should provide id(it is GUID).
For example
Register Application
Grant API permissions
Under Manage, select API permissions.
Under Configured permissions, select Add a permission.
Select the Microsoft APIs tab, then select Microsoft Graph.
Select Application permissions.
Select the checkbox of the permission Application.ReadWrite.All to grant to your application.
Select Add permissions. As directed, wait a few minutes before proceeding to the next step.
Select Grant admin consent for (your tenant name).
Create a client secret
code
static async Task Main(string[] args)
{
string clientId = "0159ec7d-f99f-***";
string clientSecret = "G_fM3QKa***essTRX23t1_o";
string tenantDomain = "{your tenat name}.onmicrosoft.com";
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantDomain)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
var id = "fa89ac50-d5fd-47cb-9f3f-833f413a2ed4";
var app =await graphClient.Applications[id].Request().GetAsync();
var updated = new Application();
if (app.IdentifierUris.ToList().Count == 0) {
updated.IdentifierUris = new string[] { $"https://{tenantDomain}/{app.AppId}" };
}
var appscope = app.Api.Oauth2PermissionScopes.ToList();
var newScope = new PermissionScope
{
Id = Guid.NewGuid(),
AdminConsentDescription = "Allow the application to have read-only access to all Employee data",
AdminConsentDisplayName = "Read-only access to Employee records",
IsEnabled = true,
Type = "Admin",
Value = "Employees.Read.All"
};
appscope.Add(newScope);
updated.Api = new ApiApplication { Oauth2PermissionScopes =appscope };
await graphClient.Applications[id].Request().UpdateAsync(updated);
}
For more details, please refer to here.

Can't create custom attributes in Azure AD B2C with asp.net core Graph API

In my Azure B2C directory I have created a custom attribute called EmployeeId. I am creating the users with the Microsoft Graph library. I followed the example from this GitHub Example.
My actual user creation code looks like this:
public async Task InsertEmployee(Employee employee)
{
IDictionary<string, object> extensionInstance = new Dictionary<string, object>();
extensionInstance.Add("EmployeeId", employee.EmployeeId.ToString());
var user = new B2cUserModel
{
DisplayName = $"{employee.EmployeeFirstName} {employee.EmployeeLastName}",
GivenName = employee.EmployeeFirstName,
Surname = employee.EmployeeLastName,
Password = employee.Password,
Identities = new List<ObjectIdentity> {
new ObjectIdentity {
SignInType = "emailAddress",
IssuerAssignedId = employee.EmployeeEmail
}
},
EmployeeId = employee.EmployeeId.ToString()
AdditionalData = extensionInstance
};
user.SetB2CProfile(_domain);
await _client.Users.Request().AddAsync(user);
}
}
But whenever I retrieve the user details either through code or through a user_flow EmployeeId is always null. Can anyone spot what I'm doing wrong?
The custom attribute in Azure B2C is stored in Graph as such a format: extension_{client id of WebApp-GraphAPI-DirectoryExtensions}_{custom attribute}. See reference here.
You can find the client id of WebApp-GraphAPI-DirectoryExtensions Azure AD app in Azure Portal -> App registrations.
So in this case, you should use:
extensionInstance.Add("extension_{client id of WebApp-GraphAPI-DirectoryExtensions}_EmployeeId", employee.EmployeeId.ToString());

C# Authentication error in google dialogflow API

How do i fix this. I want to set my authentication in my code and not on the machine.
I have checked almost every answer on stackoverflow and github, but none has a good explanation.
How do i pass the credentials to the create intent, it throws this error.
InvalidOperationException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
GoogleCredential credential =
GoogleCredential.FromFile(file);
//var credential = GoogleCredential.FromStream(
// Assembly.GetExecutingAssembly().GetManifestResourceStream("chatbot-a90a9-8f2fb910202d.json"))
// .CreateScoped(IntentsClient.DefaultScopes);
var storage = StorageClient.Create(credential);
var client = IntentsClient.Create();
var text = new Intent.Types.Message.Types.Text();
text.Text_.Add("Message Text");
var message = new Intent.Types.Message()
{
Text = text
};
var trainingPhrasesParts = new List<string>
{
"Book a fligt",
"check cheap flights"
};
var phraseParts = new List<Intent.Types.TrainingPhrase.Types.Part>();
foreach (var part in trainingPhrasesParts)
{
phraseParts.Add(new Intent.Types.TrainingPhrase.Types.Part()
{
Text = part
});
}
var trainingPhrase = new Intent.Types.TrainingPhrase();
trainingPhrase.Parts.AddRange(phraseParts);
var intent = new Intent();
intent.DisplayName = "test";
intent.Messages.Add(message);
intent.TrainingPhrases.Add(trainingPhrase);
var newIntent = client.CreateIntent(
parent: new AgentName("chatbot-a90a9"),
intent: intent
);
SOLVED.
I change
var client = IntentsClient.Create();
To
IntentsClientBuilder builder = new IntentsClientBuilder
{
CredentialsPath = file, // Relative to where the code is executing or absolute path.
// Scopes = IntentsClient.DefaultScopes // Commented out because there's no need to specify this since you are using the defaults and all default values will be automatically used for values not specified in the builder.
};
IntentsClient client = builder.Build();

Context Properties Not Recorded From WPF To Application Insights

I am trying to record telemetry to Application Insights from a WPF app. Events and page views are being logged but the context properties are not being logged alongside them.
I have intitialised the client like:
internal InsightsLogging(string instrumentationKey)
{
TelemetryConfiguration configuration = TelemetryConfiguration.Active;
configuration.InstrumentationKey = instrumentationKey;
QuickPulseTelemetryProcessor processor = null;
configuration.TelemetryProcessorChainBuilder
.Use((next) =>
{
processor = new QuickPulseTelemetryProcessor(next);
return processor;
})
.Build();
var QuickPulse = new QuickPulseTelemetryModule();
QuickPulse.Initialize(configuration);
QuickPulse.RegisterTelemetryProcessor(processor);
Client = new TelemetryClient(configuration);
Client.InstrumentationKey = instrumentationKey;
Client.Context.Session.Id = Guid.NewGuid().ToString();
Client.Context.Device.OperatingSystem = Environment.OSVersion.ToString();
Client.Context.Device.Id = EnvironmentUtility.GetMACAddress();
Client.Context.Component.Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Client.Context.User.Id = LoggingDataProvider.User;
Client.Context.User.AuthenticatedUserId = LoggingDataProvider.User;
Client.Context.User.AccountId = LoggingDataProvider.Account;
Client.Context.Component.Version = Assembly.GetEntryAssembly().GetName().Version.ToString();
Client.Context.User.UserAgent = "App";
}
The logs end up looking like:
Notice that none of the "user_*" columns are not populated. And it is worth noting that the appName is incorrect as well - it is the name of the application insights instance on Azure.

Microsoft.Web.Deployment: How to take the target offline before syncing the new version?

I have a problem with the Microsoft.Web.Deployment package. someone here could tell me, how i must write / configure the sync-process, that the target will be shutdown, before updating it with the new version?
here is my snippet:
var publishSettings = GetPublishSettings(subscriptionId, resourcegroupName, websiteName);
var sourceBaseOptions = new DeploymentBaseOptions();
var targetBaseOptions = new DeploymentBaseOptions
{
ComputerName = publishSettings.ComputerName,
UserName = publishSettings.Username,
Password = publishSettings.Password,
AuthenticationType = "basic",
TraceLevel = Verbose
};
targetBaseOptions.Trace += TargetBaseOptions_Trace;
var syncOptions = new DeploymentSyncOptions
{
DoNotDelete = false,
WhatIf = false,
UseChecksum = true
};
using (var deploymentObject = DeploymentManager.CreateObject(DeploymentWellKnownProvider.ContentPath, Path.GetFullPath(websitePath), sourceBaseOptions))
{
var summary = deploymentObject.SyncTo(DeploymentWellKnownProvider.ContentPath, publishSettings.SiteName, targetBaseOptions, syncOptions);
if (summary.Errors > 0) throw new Exception("Website Deployment failed");
if (summary.Errors == 0)
{
Console.WriteLine($"{publishSettings.SiteName}: erfolgreich");
}
}
i could imagine that it is something in the DeploymentSyncOptions
thank you guys
From Microsoft.Web.Deployment, I could not find it provides method or option to manage (stop, restart etc) Azure web site. If you’d like to stop your Azure web site before you do deployment, you could try to use Microsoft.Azure.Management.WebSites that provides website management capabilities for Microsoft Azure.
WebSiteManagementClient websiteManagementClient = new WebSiteManagementClient(cred);
websiteManagementClient.SubscriptionId = "your subscription id here";
websiteManagementClient.Sites.StopSite(AzureResourceGroup, siteName);
and you could use websiteManagementClient.Sites.GetSite(AzureResourceGroup, siteName).State to check the site state.

Categories

Resources