github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/api/container/registryv1/tokens.go (about) 1 package registryv1 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 "strconv" 8 "strings" 9 10 "github.com/IBM-Cloud/bluemix-go/client" 11 "github.com/IBM-Cloud/bluemix-go/helpers" 12 "github.com/IBM-Cloud/bluemix-go/rest" 13 ) 14 15 type TokenTargetHeader struct { 16 AccountID string 17 } 18 19 //ToMap ... 20 func (c TokenTargetHeader) ToMap() map[string]string { 21 m := make(map[string]string, 1) 22 m[accountIDHeader] = c.AccountID 23 return m 24 } 25 26 //Subnets interface 27 type Tokens interface { 28 GetToken(tokenUUID string, target TokenTargetHeader) (*TokenResponse, error) 29 GetTokens(target TokenTargetHeader) (*GetTokensResponse, error) 30 DeleteToken(tokenUUID string, target TokenTargetHeader) error 31 DeleteTokenByDescription(tokenDescription string, target TokenTargetHeader) error 32 IssueToken(params IssueTokenRequest, target TokenTargetHeader) (*TokenResponse, error) 33 } 34 35 type tokens struct { 36 client *client.Client 37 } 38 39 func newTokenAPI(c *client.Client) Tokens { 40 return &tokens{ 41 client: c, 42 } 43 } 44 45 type GetTokensResponse struct { 46 Tokens []struct { 47 ID string `json:"_id,omitempty"` 48 Owner string `json:"owner,omitempty"` 49 Token string `json:"token,omitempty"` 50 Description string `json:"secondary_owner,omitempty"` 51 Readonly bool `json:"readonly,omitempty"` 52 Revoked bool `json:"revoked,omitempty"` 53 Expiry int64 `json:"expiry,omitempty"` 54 EncryptedToken string `json:"encrypted_token,omitempty"` 55 } `json:"tokens,omitempty"` 56 } 57 type TokenResponse struct { 58 ID string 59 Token string `json:"token,omitempty"` 60 } 61 62 /*TokenIssueParams contains all the parameters to send to the API endpoint 63 for the token issue operation typically these are written to a http.Request 64 */ 65 type IssueTokenRequest struct { 66 /*Description 67 Specifies a description for the token so it can be more easily identified. If this option is specified more than once, the last parsed setting is the setting that is used. 68 */ 69 Description string 70 /*Permanent 71 When specified, the access token does not expire. If this option is specified more than once, the last parsed setting is the setting that is used. 72 */ 73 Permanent bool 74 /*Write 75 When specified, the token provides write access to registry namespaces in your IBM Cloud account. If this option is not specified, or is set to false, the token provides read-only access. If this option is specified more than once, the last parsed setting is the setting that is used. 76 */ 77 Write bool 78 } 79 80 func DefaultIssueTokenRequest() *IssueTokenRequest { 81 return &IssueTokenRequest{ 82 Description: "", 83 Permanent: false, 84 Write: false, 85 } 86 } 87 88 //GetTokens ... 89 func (r *tokens) GetTokens(target TokenTargetHeader) (*GetTokensResponse, error) { 90 91 var retVal GetTokensResponse 92 req := rest.GetRequest(helpers.GetFullURL(*r.client.Config.Endpoint, "/api/v1/tokens")) 93 94 for key, value := range target.ToMap() { 95 req.Set(key, value) 96 } 97 98 _, err := r.client.SendRequest(req, &retVal) 99 if err != nil { 100 return nil, err 101 } 102 return &retVal, err 103 } 104 105 func getTokID(token string) (string, error) { 106 parts := strings.Split(token, ".") 107 if len(parts) != 3 { 108 return "", fmt.Errorf("Corrupt Token, not enough parts") 109 } 110 decodedBytes, decerr := base64.RawStdEncoding.DecodeString(parts[1]) 111 if decerr != nil { 112 return "", fmt.Errorf("Corrupt Token, could not decode, error: %v", decerr) 113 } 114 jwtID := struct { 115 ID string `json:"jti"` 116 }{""} 117 jerr := json.Unmarshal(decodedBytes, &jwtID) 118 if jerr != nil { 119 return "", fmt.Errorf("Corrupt Token, could not decode, error: %v", jerr) 120 } 121 return jwtID.ID, nil 122 } 123 124 //GetToken ... 125 func (r *tokens) GetToken(tokenUUID string, target TokenTargetHeader) (*TokenResponse, error) { 126 127 var retVal TokenResponse 128 req := rest.GetRequest(helpers.GetFullURL(*r.client.Config.Endpoint, fmt.Sprintf("/api/v1/tokens/%s", tokenUUID))) 129 130 for key, value := range target.ToMap() { 131 req.Set(key, value) 132 } 133 134 _, err := r.client.SendRequest(req, &retVal) 135 if err == nil { 136 retVal.ID = tokenUUID 137 } else { 138 return nil, err 139 } 140 return &retVal, err 141 } 142 143 //Add ... 144 func (r *tokens) IssueToken(params IssueTokenRequest, target TokenTargetHeader) (*TokenResponse, error) { 145 146 var retVal TokenResponse 147 req := rest.PostRequest(helpers.GetFullURL(*r.client.Config.Endpoint, "/api/v1/tokens")). 148 Query("description", params.Description). 149 Query("permanent", strconv.FormatBool(params.Permanent)). 150 Query("write", strconv.FormatBool(params.Permanent)) 151 152 for key, value := range target.ToMap() { 153 req.Set(key, value) 154 } 155 156 _, err := r.client.SendRequest(req, &retVal) 157 if err == nil { 158 retVal.ID, err = getTokID(retVal.Token) 159 } else { 160 return nil, err 161 } 162 return &retVal, err 163 } 164 165 //Delete... 166 func (r *tokens) DeleteToken(tokenUUID string, target TokenTargetHeader) error { 167 req := rest.DeleteRequest(helpers.GetFullURL(*r.client.Config.Endpoint, fmt.Sprintf("/api/v1/tokens/%s", tokenUUID))) 168 169 for key, value := range target.ToMap() { 170 req.Set(key, value) 171 } 172 173 _, err := r.client.SendRequest(req, nil) 174 return err 175 } 176 177 //Delete By Description 178 func (r *tokens) DeleteTokenByDescription(tokenDescription string, target TokenTargetHeader) error { 179 req := rest.DeleteRequest(helpers.GetFullURL(*r.client.Config.Endpoint, "/api/v1/tokens")). 180 Query("secondaryOwner", tokenDescription) 181 182 for key, value := range target.ToMap() { 183 req.Set(key, value) 184 } 185 186 _, err := r.client.SendRequest(req, nil) 187 return err 188 }