@@ -6,6 +6,7 @@ package api
66import (
77 "bytes"
88 "context"
9+ "fmt"
910 "io/ioutil"
1011 "strings"
1112 "time"
@@ -93,7 +94,9 @@ func newAcrCLIClientWithBasicAuth(loginURL string, username string, password str
9394func newAcrCLIClientWithBearerAuth (loginURL string , refreshToken string ) (AcrCLIClient , error ) {
9495 newAcrCLIClient := newAcrCLIClient (loginURL )
9596 ctx := context .Background ()
96- accessTokenResponse , err := newAcrCLIClient .AutorestClient .GetAcrAccessToken (ctx , loginURL , "registry:catalog:* repository:*:*" , refreshToken )
97+ // For ABAC-enabled registries, only request catalog scope initially
98+ // Repository-specific scopes will be requested when needed
99+ accessTokenResponse , err := newAcrCLIClient .AutorestClient .GetAcrAccessToken (ctx , loginURL , "registry:catalog:*" , refreshToken )
97100 if err != nil {
98101 return newAcrCLIClient , err
99102 }
@@ -152,9 +155,9 @@ func GetAcrCLIClientWithAuth(loginURL string, username string, password string,
152155 return & acrClient , nil
153156}
154157
155- // refreshAcrCLIClientToken obtains a new token and gets its expiration time.
156- func refreshAcrCLIClientToken (ctx context.Context , c * AcrCLIClient ) error {
157- accessTokenResponse , err := c .AutorestClient .GetAcrAccessToken (ctx , c .loginURL , "repository:*:*" , c .token .RefreshToken )
158+ // refreshAcrCLIClientToken obtains a new token with the specified scope and gets its expiration time.
159+ func refreshAcrCLIClientToken (ctx context.Context , c * AcrCLIClient , scope string ) error {
160+ accessTokenResponse , err := c .AutorestClient .GetAcrAccessToken (ctx , c .loginURL , scope , c .token .RefreshToken )
158161 if err != nil {
159162 return err
160163 }
@@ -172,6 +175,19 @@ func refreshAcrCLIClientToken(ctx context.Context, c *AcrCLIClient) error {
172175 return nil
173176}
174177
178+ // refreshTokenForRepository obtains a new token scoped to a specific repository with all permissions.
179+ // This supports both ABAC and non-ABAC registries.
180+ func refreshTokenForRepository (ctx context.Context , c * AcrCLIClient , repoName string ) error {
181+ // For specific repository operations, request full permissions on that repository
182+ scope := fmt .Sprintf ("repository:%s:*" , repoName )
183+ return refreshAcrCLIClientToken (ctx , c , scope )
184+ }
185+
186+ // refreshTokenForCatalog obtains a new token with catalog access only.
187+ func refreshTokenForCatalog (ctx context.Context , c * AcrCLIClient ) error {
188+ return refreshAcrCLIClientToken (ctx , c , "registry:catalog:*" )
189+ }
190+
175191// getExpiration is used to obtain the expiration out of a jwt token.
176192func getExpiration (token string ) (int64 , error ) {
177193 parser := jwt.Parser {SkipClaimsValidation : true }
@@ -200,7 +216,7 @@ func (c *AcrCLIClient) isExpired() bool {
200216// GetAcrTags list the tags of a repository with their attributes.
201217func (c * AcrCLIClient ) GetAcrTags (ctx context.Context , repoName string , orderBy string , last string ) (* acrapi.RepositoryTagsType , error ) {
202218 if c .isExpired () {
203- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
219+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
204220 return nil , err
205221 }
206222 }
@@ -215,7 +231,7 @@ func (c *AcrCLIClient) GetAcrTags(ctx context.Context, repoName string, orderBy
215231// DeleteAcrTag deletes the tag by reference.
216232func (c * AcrCLIClient ) DeleteAcrTag (ctx context.Context , repoName string , reference string ) (* autorest.Response , error ) {
217233 if c .isExpired () {
218- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
234+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
219235 return nil , err
220236 }
221237 }
@@ -229,7 +245,7 @@ func (c *AcrCLIClient) DeleteAcrTag(ctx context.Context, repoName string, refere
229245// GetAcrManifests list all the manifest in a repository with their attributes.
230246func (c * AcrCLIClient ) GetAcrManifests (ctx context.Context , repoName string , orderBy string , last string ) (* acrapi.Manifests , error ) {
231247 if c .isExpired () {
232- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
248+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
233249 return nil , err
234250 }
235251 }
@@ -243,7 +259,7 @@ func (c *AcrCLIClient) GetAcrManifests(ctx context.Context, repoName string, ord
243259// DeleteManifest deletes a manifest using the digest as a reference.
244260func (c * AcrCLIClient ) DeleteManifest (ctx context.Context , repoName string , reference string ) (* autorest.Response , error ) {
245261 if c .isExpired () {
246- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
262+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
247263 return nil , err
248264 }
249265 }
@@ -258,7 +274,7 @@ func (c *AcrCLIClient) DeleteManifest(ctx context.Context, repoName string, refe
258274// This is used when a manifest list is wanted, first the bytes are obtained and then unmarshalled into a new struct.
259275func (c * AcrCLIClient ) GetManifest (ctx context.Context , repoName string , reference string ) ([]byte , error ) {
260276 if c .isExpired () {
261- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
277+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
262278 return nil , err
263279 }
264280 }
@@ -298,7 +314,7 @@ func (c *AcrCLIClient) GetManifest(ctx context.Context, repoName string, referen
298314// GetAcrManifestAttributes gets the attributes of a manifest.
299315func (c * AcrCLIClient ) GetAcrManifestAttributes (ctx context.Context , repoName string , reference string ) (* acrapi.ManifestAttributes , error ) {
300316 if c .isExpired () {
301- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
317+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
302318 return nil , err
303319 }
304320 }
@@ -312,7 +328,7 @@ func (c *AcrCLIClient) GetAcrManifestAttributes(ctx context.Context, repoName st
312328// UpdateAcrTagAttributes updates tag attributes to enable/disable deletion and writing.
313329func (c * AcrCLIClient ) UpdateAcrTagAttributes (ctx context.Context , repoName string , reference string , value * acrapi.ChangeableAttributes ) (* autorest.Response , error ) {
314330 if c .isExpired () {
315- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
331+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
316332 return nil , err
317333 }
318334 }
@@ -326,7 +342,7 @@ func (c *AcrCLIClient) UpdateAcrTagAttributes(ctx context.Context, repoName stri
326342// UpdateAcrManifestAttributes updates manifest attributes to enable/disable deletion and writing.
327343func (c * AcrCLIClient ) UpdateAcrManifestAttributes (ctx context.Context , repoName string , reference string , value * acrapi.ChangeableAttributes ) (* autorest.Response , error ) {
328344 if c .isExpired () {
329- if err := refreshAcrCLIClientToken (ctx , c ); err != nil {
345+ if err := refreshTokenForRepository (ctx , c , repoName ); err != nil {
330346 return nil , err
331347 }
332348 }
0 commit comments