Hello,
I am unable to fetch attributes for a particular container repository of Azure Container registry.
I have also tried weird combinations to run this.
Attempt 1
loginURI := "https://management.azure.com/subscriptions/" + subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.ContainerRegistry/registries/" + registryName + ".azurecr.io"
Attempt 1 error message
```2020/04/28 13:39:55 Error while fetching location list, containerregistry.RepositoryClient#GetAttributes: Failure responding to request: StatusCode=400 -- Original Error: autorest/
azure: Service returned an error. Status=400 Code="MissingApiVersionParameter" Message="The api-version query parameter (?api-version=) is required for all requests."
Attempt 2
loginURI := "https://" + registryName + ".azurecr.io/acr/v1/hello-world"
Attempt 3
loginURI := "https://management.azure.com/subscriptions/" + subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.ContainerRegistry/registries/" + registryName + ".azurecr.io?api-version=2019-08-15-preview"
> Attempt 3 error message
2020/04/28 13:33:45 Error while fetching location list, containerregistry.RepositoryClient#GetAttributes: Failure responding to request: StatusCode=400 -- Original Error: autorest/
azure: Service returned an error. Status=400 Code="NoRegisteredProviderFound" Message="No registered resource provider found for location 'westus' and API version '2019-08-15-previ
ew/acr/v1/hello-world?api-version=2019-08-15-preview' for type 'registries'. The supported api-versions are '2016-06-27-preview, 2017-03-01, 2017-10-01, 2019-05-01, 2019-12-01-prev
iew, 2017-06-01-preview'. The supported locations are 'westus, eastus, southcentralus, westeurope, northeurope, uksouth, ukwest, australiaeast, australiasoutheast, centralindia, ko
reacentral, francecentral, southafricanorth, uaenorth, eastasia, japaneast, japanwest, southeastasia, southindia, brazilsouth, canadaeast, canadacentral, centralus, eastus2, northc
entralus, westcentralus, westus2, switzerlandnorth'."
But still no luck while fetching attributes
Can anyone suggest the correct me away if I am doing something wrong here?
Is this the correct way of providing loginURI for Container repository Client?
Do we need to specify ApiVersion for the same, if yes then how?
Is there any examples available for ACR's Repository so I can refer it.
Sample code can be found down here
Go version
go1.14.2 windows/amd64
package main
import (
"context"
"fmt"
"github.com/Azure/azure-sdk-for-go/profiles/preview/preview/containerregistry/runtime/containerregistry"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-11-01/subscriptions"
"github.com/Azure/go-autorest/autorest/azure/auth"
"log"
"os"
)
func main() {
subscriptionId := ""
clientId := ""
clientSecret := ""
tenantId := ""
resourceGroupName := ""
registryName := "test"
repositoryName := "hello-world"
err := os.Setenv("AZURE_CLIENT_ID", clientId)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_CLIENT_SECRET", clientSecret)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_TENANT_ID", tenantId)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_SUBSCRIPTION_ID", subscriptionId)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
authorizer, err := auth.NewAuthorizerFromEnvironment()
if err != nil {
log.Printf("Error while creating an new authentication, %v ", err)
}
loginURI := "https://management.azure.com/subscriptions/" + subscriptionId + "/resourceGroups/" + resourceGroupName + "/providers/Microsoft.ContainerRegistry/registries/"
subscriptionsClient := containerregistry.NewRepositoryClient(loginURI)
subscriptionsClient.Authorizer = authorizer
attributes, err2 := subscriptionsClient.GetAttributes(context.Background(), registryName+ "/"+ repositoryName)
if err2 != nil {
log.Printf("Error while fetching attributes, %v ", err)
}
fmt.Print(attributes)
}
```
Hi @click2cloud-tathagat thanks for this issue!
The package you are using is a data-plane package which I am not quite familiar with...
Since profiles are just alias of some real packages, the real package for it should be github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry. And for mgmt packages, the default login URI is just https://management.azure.com, how about you have a try on this:
loginURI := "https://" + registryName + ".azurecr.io/
One proof that can support my assumption is here, go SDK will append the acr/v1 part for you, therefore I suppose the first part should be sufficient.
Hi @ArcturusZhang
Thanks for your response
In my code I imported the package that you mentioned above and also used loginURI i.e
github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry
loginURI := https://testrepository.azurecr.io
you can also find the below Sample code,
err := os.Setenv("AZURE_CLIENT_ID", client_id)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_CLIENT_SECRET", client_secret)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_TENANT_ID", tenant_id)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_SUBSCRIPTION_ID", subscription_id)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
authorizer, err := auth.NewAuthorizerFromEnvironment()
if err != nil {
log.Printf(err)
}
repositoryClient :=containerregistry.NewRepositoryClient("https://testrepository.azurecr.io")
repositoryClient.Authorizer = authorizer
replist,err:= repositoryClient.GetAttributes(context.Background(),"hello-world")
if err != nil {
log.Printf(err)
}
But we are getting the following error:

I guess while fetching the Repository Information from the container registry they required first username and password to login the azure container registry but we are unable to find where to assign the username and password in the above code.
I also try one below approach to assign username and password in our code but it does not work i.e
err = os.Setenv("AZURE_USERNAME", username)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
err = os.Setenv("AZURE_PASSWORD", password)
if err != nil {
log.Printf("Error while setting env variable, %v ", err)
}
Can you please give us some suggestion for the same.
If it is the service that wants a password, just assigning it to env variable may not work, I suppose...
I am not an expert on how to use the ACR, therefore I have tagged this issue and someone from service team may come and give you some advice about this.
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @yugangw-MSFT, @toddysm.
We are taking a look
@click2cloud-tathagat
You are trying to carry out a dataplane registry operation. This requires using an ACR access token and not an AAD token. NewAuthorizerFromEnvironment returns an authorizer that uses an AAD token directly. The solution is to implement a BearerAuthorizer that exchanges an AAD token for an access token according to this doc (ACR AAD OAuth). Or to use BasicAuthentication (registry admin credentials).
the azure/auth modules function auth.NewAuthorizerFromEnvironment() returns a bearer authorizer. Before a request is sent, the authorizer applies a bearer token via the Authorization header. This bearer token is an AAD token that was exchanged for the credentials you passed through the environment. This works well for azure management operations. Including ACR management operations (create a registry, list registries, add a registry replication, etc.)
However ACR's dataplane auth works differently. Just like ACR's dataplane operations use a different API from its management operations, its authentication API is different. For ACR dataplane basic auth, you use the registry admin creds. For bearer auth, you have to exchange an AAD token for an ACR token which can be used as a bearer token.
This means that unfortunately, you can't leverage go-autorest/autorest/azure/auth.NewAuthorizerFromEnvironment() as it assumes that the AAD token is to be used directly as the bearer token.
Rather you will need to probably implement a BearerAuthorizer that properly exchanges the AAD token for an ACR token. (More specifically AAD token -> ACR refresh Token -> ACR access token)
Here is a doc that explains ACR oauth for dataplane operations.
Links:
p.s
az acr login is sufficient to authenticate when using docker for dataplane operations (push / pull). Most dataplane operations (docker push, pull, etc) are done via the docker client.
Please let me know if you have any more questions and any way I can help. I can help with writing a sample BearerAuthorizer.
Thank you so much for the response and will let you know if any issue occurs again.
Will close the issue within 2 weeks if everything seems okay.
Most helpful comment
We are taking a look