github.com/google/go-github/v49@v49.1.0/github/actions_secrets.go (about) 1 // Copyright 2020 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "strconv" 13 ) 14 15 // PublicKey represents the public key that should be used to encrypt secrets. 16 type PublicKey struct { 17 KeyID *string `json:"key_id"` 18 Key *string `json:"key"` 19 } 20 21 // UnmarshalJSON implements the json.Unmarshaler interface. 22 // This ensures GitHub Enterprise versions which return a numeric key id 23 // do not error out when unmarshaling. 24 func (p *PublicKey) UnmarshalJSON(data []byte) error { 25 var pk struct { 26 KeyID interface{} `json:"key_id,string"` 27 Key *string `json:"key"` 28 } 29 30 if err := json.Unmarshal(data, &pk); err != nil { 31 return err 32 } 33 34 p.Key = pk.Key 35 36 switch v := pk.KeyID.(type) { 37 case nil: 38 return nil 39 case string: 40 p.KeyID = &v 41 case float64: 42 p.KeyID = String(strconv.FormatFloat(v, 'f', -1, 64)) 43 default: 44 return fmt.Errorf("unable to unmarshal %T as a string", v) 45 } 46 47 return nil 48 } 49 50 func (s *ActionsService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { 51 req, err := s.client.NewRequest("GET", url, nil) 52 if err != nil { 53 return nil, nil, err 54 } 55 56 pubKey := new(PublicKey) 57 resp, err := s.client.Do(ctx, req, pubKey) 58 if err != nil { 59 return nil, resp, err 60 } 61 62 return pubKey, resp, nil 63 } 64 65 // GetRepoPublicKey gets a public key that should be used for secret encryption. 66 // 67 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-a-repository-public-key 68 func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { 69 url := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo) 70 return s.getPublicKey(ctx, url) 71 } 72 73 // GetOrgPublicKey gets a public key that should be used for secret encryption. 74 // 75 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-organization-public-key 76 func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { 77 url := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org) 78 return s.getPublicKey(ctx, url) 79 } 80 81 // GetEnvPublicKey gets a public key that should be used for secret encryption. 82 // 83 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-environment-public-key 84 func (s *ActionsService) GetEnvPublicKey(ctx context.Context, repoID int, env string) (*PublicKey, *Response, error) { 85 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/public-key", repoID, env) 86 return s.getPublicKey(ctx, url) 87 } 88 89 // Secret represents a repository action secret. 90 type Secret struct { 91 Name string `json:"name"` 92 CreatedAt Timestamp `json:"created_at"` 93 UpdatedAt Timestamp `json:"updated_at"` 94 Visibility string `json:"visibility,omitempty"` 95 SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` 96 } 97 98 // Secrets represents one item from the ListSecrets response. 99 type Secrets struct { 100 TotalCount int `json:"total_count"` 101 Secrets []*Secret `json:"secrets"` 102 } 103 104 func (s *ActionsService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { 105 u, err := addOptions(url, opts) 106 if err != nil { 107 return nil, nil, err 108 } 109 110 req, err := s.client.NewRequest("GET", u, nil) 111 if err != nil { 112 return nil, nil, err 113 } 114 115 secrets := new(Secrets) 116 resp, err := s.client.Do(ctx, req, &secrets) 117 if err != nil { 118 return nil, resp, err 119 } 120 121 return secrets, resp, nil 122 } 123 124 // ListRepoSecrets lists all secrets available in a repository 125 // without revealing their encrypted values. 126 // 127 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-repository-secrets 128 func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { 129 url := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo) 130 return s.listSecrets(ctx, url, opts) 131 } 132 133 // ListOrgSecrets lists all secrets available in an organization 134 // without revealing their encrypted values. 135 // 136 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-organization-secrets 137 func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { 138 url := fmt.Sprintf("orgs/%v/actions/secrets", org) 139 return s.listSecrets(ctx, url, opts) 140 } 141 142 // ListEnvSecrets lists all secrets available in an environment. 143 // 144 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-environment-secrets 145 func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { 146 url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) 147 return s.listSecrets(ctx, url, opts) 148 } 149 150 func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { 151 req, err := s.client.NewRequest("GET", url, nil) 152 if err != nil { 153 return nil, nil, err 154 } 155 156 secret := new(Secret) 157 resp, err := s.client.Do(ctx, req, secret) 158 if err != nil { 159 return nil, resp, err 160 } 161 162 return secret, resp, nil 163 } 164 165 // GetRepoSecret gets a single repository secret without revealing its encrypted value. 166 // 167 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-a-repository-secret 168 func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { 169 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 170 return s.getSecret(ctx, url) 171 } 172 173 // GetOrgSecret gets a single organization secret without revealing its encrypted value. 174 // 175 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-organization-secret 176 func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { 177 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 178 return s.getSecret(ctx, url) 179 } 180 181 // GetEnvSecret gets a single environment secret without revealing its encrypted value. 182 // 183 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-environment-secret 184 func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { 185 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 186 return s.getSecret(ctx, url) 187 } 188 189 // SelectedRepoIDs are the repository IDs that have access to the actions secrets. 190 type SelectedRepoIDs []int64 191 192 // EncryptedSecret represents a secret that is encrypted using a public key. 193 // 194 // The value of EncryptedValue must be your secret, encrypted with 195 // LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) 196 // using the public key retrieved using the GetPublicKey method. 197 type EncryptedSecret struct { 198 Name string `json:"-"` 199 KeyID string `json:"key_id"` 200 EncryptedValue string `json:"encrypted_value"` 201 Visibility string `json:"visibility,omitempty"` 202 SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` 203 } 204 205 func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { 206 req, err := s.client.NewRequest("PUT", url, eSecret) 207 if err != nil { 208 return nil, err 209 } 210 211 return s.client.Do(ctx, req, nil) 212 } 213 214 // CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. 215 // 216 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-a-repository-secret 217 func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { 218 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) 219 return s.putSecret(ctx, url, eSecret) 220 } 221 222 // CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. 223 // 224 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-an-organization-secret 225 func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { 226 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) 227 return s.putSecret(ctx, url, eSecret) 228 } 229 230 // CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. 231 // 232 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-an-environment-secret 233 func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { 234 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) 235 return s.putSecret(ctx, url, eSecret) 236 } 237 238 func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { 239 req, err := s.client.NewRequest("DELETE", url, nil) 240 if err != nil { 241 return nil, err 242 } 243 244 return s.client.Do(ctx, req, nil) 245 } 246 247 // DeleteRepoSecret deletes a secret in a repository using the secret name. 248 // 249 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-a-repository-secret 250 func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { 251 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 252 return s.deleteSecret(ctx, url) 253 } 254 255 // DeleteOrgSecret deletes a secret in an organization using the secret name. 256 // 257 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-an-organization-secret 258 func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { 259 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 260 return s.deleteSecret(ctx, url) 261 } 262 263 // DeleteEnvSecret deletes a secret in an environment using the secret name. 264 // 265 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-an-environment-secret 266 func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { 267 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 268 return s.deleteSecret(ctx, url) 269 } 270 271 // SelectedReposList represents the list of repositories selected for an organization secret. 272 type SelectedReposList struct { 273 TotalCount *int `json:"total_count,omitempty"` 274 Repositories []*Repository `json:"repositories,omitempty"` 275 } 276 277 func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { 278 u, err := addOptions(url, opts) 279 if err != nil { 280 return nil, nil, err 281 } 282 283 req, err := s.client.NewRequest("GET", u, nil) 284 if err != nil { 285 return nil, nil, err 286 } 287 288 result := new(SelectedReposList) 289 resp, err := s.client.Do(ctx, req, result) 290 if err != nil { 291 return nil, resp, err 292 } 293 294 return result, resp, nil 295 } 296 297 // ListSelectedReposForOrgSecret lists all repositories that have access to a secret. 298 // 299 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-selected-repositories-for-an-organization-secret 300 func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { 301 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 302 return s.listSelectedReposForSecret(ctx, url, opts) 303 } 304 305 func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { 306 type repoIDs struct { 307 SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` 308 } 309 310 req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) 311 if err != nil { 312 return nil, err 313 } 314 315 return s.client.Do(ctx, req, nil) 316 } 317 318 // SetSelectedReposForOrgSecret sets the repositories that have access to a secret. 319 // 320 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#set-selected-repositories-for-an-organization-secret 321 func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { 322 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 323 return s.setSelectedReposForSecret(ctx, url, ids) 324 } 325 326 func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { 327 req, err := s.client.NewRequest("PUT", url, nil) 328 if err != nil { 329 return nil, err 330 } 331 332 return s.client.Do(ctx, req, nil) 333 } 334 335 // AddSelectedRepoToOrgSecret adds a repository to an organization secret. 336 // 337 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#add-selected-repository-to-an-organization-secret 338 func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 339 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 340 return s.addSelectedRepoToSecret(ctx, url) 341 } 342 343 func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { 344 req, err := s.client.NewRequest("DELETE", url, nil) 345 if err != nil { 346 return nil, err 347 } 348 349 return s.client.Do(ctx, req, nil) 350 } 351 352 // RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. 353 // 354 // GitHub API docs: https://docs.github.com/en/rest/actions/secrets#remove-selected-repository-from-an-organization-secret 355 func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 356 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 357 return s.removeSelectedRepoFromSecret(ctx, url) 358 }