Azure / api-management-developer-portal

Developer portal provided by the Azure API Management service.
MIT License
478 stars 306 forks source link

Custom widget CICD deployment #2338

Open girish-tank-avnet opened 7 months ago

girish-tank-avnet commented 7 months ago

Hello Guys,

we have custom widgets for some functionality and have Github repository for the same. when we deploy custom widget in Azure APIM Developer portal we have to authenticate with our azure account and then after we are able to deploy custom widget.

if we do this deployment process manually then we don't have any issue to deploy as we authorize deployment with our azure account once it ask to authorized.

but now i am going to make GitHub Workflow CICD actions to deploy custom widget but my question is that how can we authenticate deployment with azure account or any way to bypass this MFA authentication?

please note that i am using GitHub workflow Actions to perform CICD.

Thanks, Girish.

JMach1 commented 7 months ago

Hello @girish-tank-avnet

we do not officially supported this as of right now.

You can take a look on how our deploy function works here. The Service Information object contains optional tokenOverride key, which you can use to set the AccessToken instead of logging in. In the Deploy function we are using the getToken method of the InteractiveBrowserCredential Class, I can imagine you could get the the AccessToken somehow else and pass it to the override, but that depends on your set up.

Hope this helps, Ján

girish-tank-avnet commented 7 months ago

Hello @JMach1 Thanks for giving answer. but if i want to get the access token then i have to create app registration in AD correct? then what type of permission i need to give and grant admin consent?

girish-tank-avnet commented 6 months ago

Hello @JMach1 would you please tell me the steps or can say process that how to get my azure account access token to pass in "tokenOverride" property in service information while deploy the custom widget?

Thanks in advance.

heller-tobias commented 5 months ago

Hello @girish-tank-avnet

We did it the following way. This is our deploy.js:

const {deployNodeJS} = require("@azure/api-management-custom-widgets-tools")
const { DefaultAzureCredential } = require("@azure/identity")  // Install this with npm

async function deploy() {
    const serviceInformation = {
        "resourceId": "REDACTED",
        "managementApiEndpoint": "https://management.azure.com",
        "apiVersion": "2019-12-01",
        "tokenOverride": await getTokenWithDefaultAzureCredentials() // Needed, since in the deployment pipeline the widget is deployed with a service principal and interactive login is not possible
    };
    const name = "REDACTED";
    const fallbackConfigPath = "./static/config.msapim.json";
    const config = {
        "interactiveBrowserCredentialOptions": {
        "redirectUri": "http://localhost:1337"
        }
    };

    await deployNodeJS(serviceInformation, name, fallbackConfigPath, config);
}

deploy().catch(error => {
    console.error(error);
});

async function getTokenWithDefaultAzureCredentials() {
    const tokenResponse = await new DefaultAzureCredential().getToken("https://management.azure.com/.default");
    console.log(tokenResponse);
    return "Bearer " + tokenResponse.token;
}

To make the DefaultAzureCredentials work, just run e.g. az login with a service principal before you run the deploy.js. -> https://learn.microsoft.com/en-us/javascript/api/overview/azure/identity-readme?view=azure-node-latest#authenticate-the-client-in-development-environment

elizalcodes commented 2 months ago

I used @heller-tobias' solution for the deployment function and it worked perfectly.

For anyone who needs to run this in Azure Pipelines CI/CD, here's our authentication solution: run the deploy.js script via AzureCLI@2 task, then you are automatically authenticated and there's not need to run az login anymore. AzureCLI@2

task: AzureCLI@2 displayName: Deploy widget inputs: azureSubscription: 'your subscription name' scriptType: 'ps' scriptLocation: inlineScript inlineScript: | node deploy.js workingDirectory: '$(Build.SourcesDirectory)/.../'