Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow authentication using RBAC instead of API Keys #427

Closed
wants to merge 17 commits into from

Conversation

adamdougal
Copy link

Required by #391

@pamelafox
Copy link
Member

@adamdougal
Copy link
Author

@pamelafox Yes! Looks like I missed that. Some roles are there already but a few are missing. I'll get them added now.

@adamdougal
Copy link
Author

@pamelafox Those have now been added

README.md Outdated Show resolved Hide resolved
@@ -8,6 +8,7 @@ param sku object = {

param authOptions object = {}
param semanticSearch string = 'disabled'
param searchApiKeyEnabled bool = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @jongio who likes to be notified about potential changes to infra/core Bicep files (as we try to reuse the same infra/core across azd templates)

infra/main.bicep Outdated
@@ -271,6 +273,46 @@ module searchRoleBackend 'core/security/role.bicep' = {
}
}

module searchRoleOpenAi 'core/security/role.bicep' = if (!searchApiKeyEnabled) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you only did the system roles, what about local server running? For the other repo with these roles, we also have the equivalent for the user. I don't recall if this repo can be run locally or not.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I tried locally and it didn't require me to add any roles. I think this is because we're still calling OpenAI with API key. I missed this before, so will make the change and push to this branch/PR along with the associated required role.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want rbac to work for the local user as well.

README.md Outdated
@@ -114,6 +114,17 @@ const getUserInfoList = async () => {
}
```

### Authenticate using Azure RBAC
To authenticate using Azure RBAC instead of the default API Keys follow the steps below:
1. Ensure role assignments listed on [this page](https://learn.microsoft.com/azure/ai-services/openai/concepts/use-your-data?tabs=ai-search#azure-role-based-access-controls-azure-rbac-for-adding-data-sources) have been created
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should mention these should be created by azd provision already

@@ -114,6 +114,17 @@ const getUserInfoList = async () => {
}
```

### Authenticate using Azure RBAC
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather the flow of the application take care of all the settings and not require the user to take manual action.

We are experimenting with adding an AZURE_AUTH_TYPE parameter that can get set to rbac or keys and the bicep does the appropriate thing based on that.

It's not finalized, but should be soon.

app.py Show resolved Hide resolved
@@ -41,3 +44,5 @@ output id string = account.id
output name string = account.name
output skuName string = account.sku.name
output key string = account.listKeys().key1
output identityPrincipalId string = account.identity.principalId
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should match the name of the other core files when they provide an id, which is just principalId

@@ -17,8 +18,8 @@ resource search 'Microsoft.Search/searchServices@2021-04-01-preview' = {
type: 'SystemAssigned'
}
properties: {
authOptions: authOptions
disableLocalAuth: false
authOptions: searchApiKeyEnabled ? authOptions : null
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Param should be something like 'authType' with allowed values of rbac or keys

@@ -41,3 +42,4 @@ output endpoint string = 'https://${name}.search.windows.net/'
output name string = search.name
output skuName string = sku.name
output adminKey string = search.listAdminKeys().primaryKey
output identityPrincipalId string = search.identity.principalId
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about name principalId

infra/main.bicep Outdated
@@ -26,6 +26,7 @@ param searchContentColumns string = 'content'
param searchFilenameColumn string = 'filepath'
param searchTitleColumn string = 'title'
param searchUrlColumn string = 'url'
param searchApiKeyEnabled bool = true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authType

infra/main.bicep Outdated
@@ -271,6 +273,46 @@ module searchRoleBackend 'core/security/role.bicep' = {
}
}

module searchRoleOpenAi 'core/security/role.bicep' = if (!searchApiKeyEnabled) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want rbac to work for the local user as well.

principalType: 'ServicePrincipal'
}
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In outputs below we shouldn't be outputting keys. You will get a bicep linter warning. Best to ask the user to manually set them with in env vars at this time until we have a secure way to store them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phew, glad to see the keys are out of this output finally! That's been a TODO (in my head) for a long time.

Another option btw is to provide a script that grabs the keys, which is what I've had to do for another repo which unfortunately requires keys:
https://github.com/Azure-Samples/contoso-chat/pull/33/files#diff-c8719e3915d76118aeee543ed85367b315252d46ef1d793635a82eaef96ce7b4R19

But probably okay not to do that here, since we now have the keyless option.

@adamdougal
Copy link
Author

Heya, thanks for your review comments! I've made some changes. Please note, I've yet to test them out. I'll update on here when I have.

@@ -43,6 +43,9 @@
},
"authClientSecret": {
"value": "${AUTH_CLIENT_SECRET}"
},
"authType": {
"value": "${AZURE_AUTH_TYPE}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll want to default this to rbac

"value": "${AZURE_AUTH_TYPE=rbac}"

app.py Outdated
@@ -40,6 +39,7 @@ def assets(path):
SEARCH_TOP_K = os.environ.get("SEARCH_TOP_K", 5)
SEARCH_STRICTNESS = os.environ.get("SEARCH_STRICTNESS", 3)
SEARCH_ENABLE_IN_DOMAIN = os.environ.get("SEARCH_ENABLE_IN_DOMAIN", "true")
AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "apikeys")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll use 'keys'

@@ -8,7 +8,7 @@ param sku object = {

param authOptions object = {}
param semanticSearch string = 'disabled'
param searchApiKeyEnabled bool = true
param authType string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add rbac default

.env.sample Outdated
@@ -1,3 +1,4 @@
AZURE_AUTH_TYPE
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the others have an =

@adamdougal
Copy link
Author

I've now tested this deployed to Azure, as well as running locally. I did not have to create any additional role assignments to get this to work locally.

@jongio
Copy link

jongio commented Dec 5, 2023

I've now tested this deployed to Azure, as well as running locally. I did not have to create any additional role assignments to get this to work locally.

Did you test with both rbac and keys in both local and azure?

@adamdougal
Copy link
Author

I've now tested this deployed to Azure, as well as running locally. I did not have to create any additional role assignments to get this to work locally.

Did you test with both rbac and keys in both local and azure?

Yep, both worked without any additional roles being required.

app.py Show resolved Hide resolved
app.py Outdated
Comment on lines 815 to 817
default_credential = DefaultAzureCredential()
token = default_credential.get_token("https://cognitiveservices.azure.com/.default")
openai.api_key = token.token
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be refactored to remove dupe code above?

@adamdougal
Copy link
Author

Heya, I believe this is ready for re-review. Thanks

@jongio
Copy link

jongio commented Jan 2, 2024

Can we move this to azure-samples github org? Not sure history on why it is in the microsoft org, but most samples go in azure-samples org. https://github.com/azure-samples

@@ -132,6 +132,6 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing
name: applicationInsightsName
}

output identityPrincipalId string = managedIdentity ? appService.identity.principalId : ''
output principalId string = managedIdentity ? appService.identity.principalId : ''
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stand corrected, the official name is identityPrincipalId

https://github.com/Azure/azure-dev/blob/main/templates/common/infra/bicep/core/host/appservice.bicep#L121

Please change it back.

@@ -41,3 +44,5 @@ output id string = account.id
output name string = account.name
output skuName string = account.sku.name
output key string = account.listKeys().key1
output principalId string = account.identity.principalId
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this to identityPrincipalId? (Sorry)

@@ -20,6 +20,9 @@ resource account 'Microsoft.CognitiveServices/accounts@2023-05-01' = {
publicNetworkAccess: publicNetworkAccess
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What updates are required? Do you just mean to pull from main?

@@ -8,6 +8,7 @@ param sku object = {

param authOptions object = {}
param semanticSearch string = 'disabled'
param authType string = 'rbac'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What updates are required? Do you just mean to pull from main?

}
}

module searchRoleOpenAi 'core/security/role.bicep' = if (authType == 'rbac') {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any new roles you create will also need to be assigned to the user's principalId, see "user roles" above.

@adamdougal
Copy link
Author

Heya @jongio, thanks for the further comments. I have addressed them and rebased from main.

Unfortunately, I have no information as to why this is not in the azure samples org.

@sarah-widder
Copy link
Contributor

Can we move this to azure-samples github org? Not sure history on why it is in the microsoft org, but most samples go in azure-samples org. https://github.com/azure-samples

We have considered moving this to the azure-samples org but haven't taken the action yet. The repo is used in multiple ways (code-first sample, source code for apps deployed from Azure OpenAI studio, storage place for public-facing utility scripts such as data preparation). For now we're keeping it here.

Copy link
Contributor

@sarah-widder sarah-widder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thank you very much for the contribution.

@adamdougal
Copy link
Author

Heya, can this be merged? Thanks

app.py Outdated
@@ -41,6 +41,7 @@ def assets(path):
SEARCH_TOP_K = os.environ.get("SEARCH_TOP_K", 5)
SEARCH_STRICTNESS = os.environ.get("SEARCH_STRICTNESS", 3)
SEARCH_ENABLE_IN_DOMAIN = os.environ.get("SEARCH_ENABLE_IN_DOMAIN", "true")
AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "rbac")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we actually have this default to "keys" and set it to "rbac" from the bicep deployment? The reason to have it default to keys is that for the case of deployment from the Azure OpenAI Studio chat playground, role assignments are not configured by default between the resources, so keys need to be used by default in that scenario.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Good point! I've just pushed that change.

adamdougal and others added 2 commits January 17, 2024 09:15
This is required as the OpenAI Studio does not create roles so this
change would break deployments from there.
@adamdougal
Copy link
Author

Heya! Is this ready to be merged now? Thanks

@adamdougal
Copy link
Author

@sarah-widder Is this still required? It looks like similar changes have been made in #460?

@adamdougal
Copy link
Author

I guess it's just the infra side of things that's still required?

@sarah-widder
Copy link
Contributor

Hey @adamdougal yes, #460 should have already addressed using RBAC in the app backend, but the infra changes you were working on to automatically assign the right roles during deployment are still needed. If you want to rebase and just keep the infra changes I will give it another review. Thanks very much for your contribution!

@adamdougal
Copy link
Author

I'm going to close this. It looks like the openai version bump has brought significant changes so a fresh PR/branch would probably be a better approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants