Compare commits

..

9 Commits

Author SHA1 Message Date
Eoin McAfee 34d66007a0 fix up naming 2023-10-19 15:38:58 +01:00
Eoin McAfee 11c1a9dac3 fixing conflicts 2023-10-19 15:36:17 +01:00
Eoin McAfee 5aaac89c8d tech qa 2023-10-19 15:32:31 +01:00
Eoin McAfee ab6b444620 adds oidc support for GAR/GCR 2023-10-19 14:21:30 +01:00
Eoin McAfee 225cc9d295 updated error messagE 2023-09-20 13:25:48 +01:00
Eoin McAfee 441a3ca577 fix docs 2023-09-20 12:02:40 +01:00
Eoin McAfee 2052b090ef adds support for GAR 2023-09-20 12:00:26 +01:00
Eoin McAfee 9b81ce8da8 test 2023-09-20 11:28:53 +01:00
Eoin McAfee d8b4088b75 adds support for GAR 2023-09-18 15:23:14 +01:00
24 changed files with 126 additions and 900 deletions
+33 -213
View File
@@ -12,7 +12,7 @@ platform:
steps:
- name: vet
image: golang:1.22.4
image: golang:1.21
commands:
- go vet ./...
environment:
@@ -22,7 +22,7 @@ steps:
path: /go
- name: test
image: golang:1.22.4
image: golang:1.21
commands:
- go test -cover ./...
environment:
@@ -55,7 +55,7 @@ platform:
steps:
- name: go build
image: golang:1.22.4
image: golang:1.21
environment:
CGO_ENABLED: 0
commands:
@@ -63,8 +63,6 @@ steps:
- go build -o release/windows/amd64/drone-ecr.exe ./cmd/drone-ecr
- go build -o release/windows/amd64/drone-gcr.exe ./cmd/drone-gcr
- go build -o release/windows/amd64/drone-acr.exe ./cmd/drone-acr
- go build -o release/windows/amd64/drone-gar.exe ./cmd/drone-gar
- name: build docker plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
settings:
@@ -125,21 +123,7 @@ steps:
purge: false
when:
event: [push, tag]
- name: build gar plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
pull: never
settings:
dockerfile: docker/gar/Dockerfile.windows.amd64.1809
repo: plugins/gar
username:
from_secret: docker_username
password:
from_secret: docker_password
auto_tag: true
auto_tag_suffix: windows-1809-amd64
purge: false
when:
event: [push, tag]
depends_on:
- testing
@@ -162,7 +146,7 @@ platform:
steps:
- name: go build
image: golang:1.22.4
image: golang:1.21
environment:
CGO_ENABLED: 0
commands:
@@ -170,9 +154,8 @@ steps:
- go build -o release/windows/amd64/drone-ecr.exe ./cmd/drone-ecr
- go build -o release/windows/amd64/drone-gcr.exe ./cmd/drone-gcr
- go build -o release/windows/amd64/drone-acr.exe ./cmd/drone-acr
- go build -o release/windows/amd64/drone-gar.exe ./cmd/drone-gar
- name: build docker plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
image: plugins/docker
settings:
dockerfile: docker/docker/Dockerfile.windows.amd64.ltsc2022
repo: plugins/docker
@@ -186,7 +169,7 @@ steps:
when:
event: [push, tag]
- name: build ecr plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
image: plugins/docker
settings:
dockerfile: docker/ecr/Dockerfile.windows.amd64.ltsc2022
repo: plugins/ecr
@@ -200,7 +183,7 @@ steps:
when:
event: [push, tag]
- name: build gcr plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
image: plugins/docker
settings:
dockerfile: docker/gcr/Dockerfile.windows.amd64.ltsc2022
repo: plugins/gcr
@@ -214,7 +197,7 @@ steps:
when:
event: [push, tag]
- name: build acr plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
image: plugins/docker
settings:
dockerfile: docker/acr/Dockerfile.windows.amd64.ltsc2022
repo: plugins/acr
@@ -227,20 +210,7 @@ steps:
purge: false
when:
event: [push, tag]
- name: build gar plugin
image: plugins/docker@sha256:f0233d950ae87ee6cb5500b2d5497fe02aa338201c0bdce2619f443fd174cfa4
settings:
dockerfile: docker/gar/Dockerfile.windows.amd64.ltsc2022
repo: plugins/gar
username:
from_secret: docker_username
password:
from_secret: docker_password
auto_tag: true
auto_tag_suffix: windows-ltsc2022-amd64
purge: false
when:
event: [push, tag]
depends_on:
- testing
@@ -264,7 +234,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-docker ./cmd/drone-docker'
environment:
@@ -275,7 +245,7 @@ steps:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-docker ./cmd/drone-docker'
environment:
@@ -285,7 +255,7 @@ steps:
- tag
- name: executable
image: golang:1.22.4
image: golang:1.21
commands:
- ./release/linux/amd64/drone-docker --help
@@ -329,7 +299,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-docker ./cmd/drone-docker'
environment:
@@ -340,7 +310,7 @@ steps:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-docker ./cmd/drone-docker'
environment:
@@ -350,7 +320,7 @@ steps:
- tag
- name: executable
image: golang:1.22.4
image: golang:1.21
commands:
- ./release/linux/arm64/drone-docker --help
@@ -429,7 +399,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-gcr ./cmd/drone-gcr'
environment:
@@ -440,7 +410,7 @@ steps:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-gcr ./cmd/drone-gcr'
environment:
@@ -474,6 +444,7 @@ trigger:
depends_on:
- linux-amd64-docker
---
kind: pipeline
name: linux-arm64-gcr
@@ -488,7 +459,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-gcr ./cmd/drone-gcr'
environment:
@@ -499,7 +470,7 @@ steps:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-gcr ./cmd/drone-gcr'
environment:
@@ -568,158 +539,7 @@ depends_on:
- windows-ltsc2022
- linux-amd64-gcr
- linux-arm64-gcr
---
kind: pipeline
name: linux-amd64-gar
type: vm
pool:
use: ubuntu
platform:
os: linux
arch: amd64
steps:
- name: build-push
image: golang:1.22.4
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-gar ./cmd/drone-gar'
environment:
CGO_ENABLED: 0
when:
event:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-gar ./cmd/drone-gar'
environment:
CGO_ENABLED: 0
when:
event:
- tag
- name: publish
image: plugins/docker:18
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
daemon_off: false
dockerfile: docker/gar/Dockerfile.linux.amd64
password:
from_secret: docker_password
repo: plugins/gar
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
trigger:
ref:
- refs/heads/master
- "refs/tags/**"
- "refs/pull/**"
depends_on:
- linux-amd64-docker
---
kind: pipeline
name: linux-arm64-gar
type: vm
pool:
use: ubuntu_arm64
platform:
os: linux
arch: arm64
steps:
- name: build-push
image: golang:1.22.4
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-gar ./cmd/drone-gar'
environment:
CGO_ENABLED: 0
when:
event:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-gar ./cmd/drone-gar'
environment:
CGO_ENABLED: 0
when:
event:
- tag
- name: publish
image: plugins/docker:18
settings:
auto_tag: true
auto_tag_suffix: linux-arm64
daemon_off: false
dockerfile: docker/gar/Dockerfile.linux.arm64
password:
from_secret: docker_password
repo: plugins/gar
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
trigger:
ref:
- refs/heads/master
- "refs/tags/**"
- "refs/pull/**"
depends_on:
- linux-arm64-docker
---
kind: pipeline
name: notifications-gar
type: vm
pool:
use: ubuntu
platform:
os: linux
arch: amd64
steps:
- name: manifest
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
password:
from_secret: docker_password
spec: docker/gar/manifest.tmpl
username:
from_secret: docker_username
trigger:
ref:
- refs/heads/master
- "refs/tags/**"
depends_on:
- windows-1809
- windows-ltsc2022
- linux-amd64-gar
- linux-arm64-gar
---
kind: pipeline
name: linux-amd64-ecr
@@ -734,7 +554,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-ecr ./cmd/drone-ecr'
environment:
@@ -744,7 +564,7 @@ steps:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-ecr ./cmd/drone-ecr'
environment:
@@ -792,7 +612,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-ecr ./cmd/drone-ecr'
environment:
@@ -802,7 +622,7 @@ steps:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-ecr ./cmd/drone-ecr'
environment:
@@ -885,7 +705,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-heroku ./cmd/drone-heroku'
environment:
@@ -895,7 +715,7 @@ steps:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/amd64/drone-heroku ./cmd/drone-heroku'
environment:
@@ -944,7 +764,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/arm64/drone-heroku ./cmd/drone-heroku'
environment:
@@ -954,7 +774,7 @@ steps:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/linux/arm64/drone-heroku ./cmd/drone-heroku'
environment:
@@ -1035,7 +855,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.build=${DRONE_BUILD_NUMBER}" -a -tags netgo -o release/linux/amd64/drone-acr ./cmd/drone-acr'
environment:
@@ -1045,7 +865,7 @@ steps:
exclude:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}" -a -tags netgo -o release/linux/amd64/drone-acr ./cmd/drone-acr'
environment:
@@ -1093,7 +913,7 @@ platform:
steps:
- name: build-push
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.build=${DRONE_BUILD_NUMBER}" -a -tags netgo -o release/linux/arm64/drone-acr ./cmd/drone-acr'
environment:
@@ -1104,7 +924,7 @@ steps:
- tag
- name: build-tag
image: golang:1.22.4
image: golang:1.21
commands:
- 'go build -v -ldflags "-X main.version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}" -a -tags netgo -o release/linux/arm64/drone-acr ./cmd/drone-acr'
environment:
+4 -16
View File
@@ -10,14 +10,6 @@
Drone plugin uses Docker-in-Docker to build and publish Docker images to a container registry. For the usage information and a listing of the available options please take a look at [the docs](http://plugins.drone.io/drone-plugins/drone-docker/).
### Git Leaks
Run the following script to install git-leaks support to this repo.
```
chmod +x ./git-hooks/install.sh
./git-hooks/install.sh
```
## Build
Build the binaries with the following commands:
@@ -33,7 +25,6 @@ go build -v -a -tags netgo -o release/linux/amd64/drone-gcr ./cmd/drone-gcr
go build -v -a -tags netgo -o release/linux/amd64/drone-ecr ./cmd/drone-ecr
go build -v -a -tags netgo -o release/linux/amd64/drone-acr ./cmd/drone-acr
go build -v -a -tags netgo -o release/linux/amd64/drone-heroku ./cmd/drone-heroku
go build -v -a -tags netgo -o release/linux/amd64/drone-gar ./cmd/drone-gar
```
## Docker
@@ -65,11 +56,6 @@ docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \
--file docker/heroku/Dockerfile.linux.amd64 --tag plugins/heroku .
docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \
--file docker/gar/Dockerfile.linux.amd64 --tag plugins/gar .
```
## Usage
@@ -136,11 +122,12 @@ type: docker
steps:
- name: push-to-gar
image: plugins/gar
image: plugins/gcr
pull: never
settings:
tag: latest
repo: project-id/repo/image-name
registry_type: GAR
location: us
json_key:
from_secret: gcr_json_key
@@ -151,11 +138,12 @@ steps:
```yaml
steps:
- name: push-to-gar
image: plugins/gar
image: plugins/gcr
pull: never
settings:
tag: latest
repo: project-id/repo/image-name
registry_type: GAR
location: europe
project_number: project-number
pool_id: workload identity pool id
-18
View File
@@ -222,21 +222,6 @@ func main() {
Usage: "docker password",
EnvVar: "PLUGIN_PASSWORD,DOCKER_PASSWORD",
},
cli.StringFlag{
Name: "docker.baseimageusername",
Usage: "Docker username for base image registry",
EnvVar: "PLUGIN_DOCKER_USERNAME,PLUGIN_BASE_IMAGE_USERNAME,DOCKER_BASE_IMAGE_USERNAME",
},
cli.StringFlag{
Name: "docker.baseimagepassword",
Usage: "Docker password for base image registry",
EnvVar: "PLUGIN_DOCKER_PASSWORD,PLUGIN_BASE_IMAGE_PASSWORD,DOCKER_BASE_IMAGE_PASSWORD",
},
cli.StringFlag{
Name: "docker.baseimageregistry",
Usage: "Docker registry for base image registry",
EnvVar: "PLUGIN_DOCKER_REGISTRY,PLUGIN_BASE_IMAGE_REGISTRY,DOCKER_BASE_IMAGE_REGISTRY",
},
cli.StringFlag{
Name: "docker.email",
Usage: "docker email",
@@ -382,9 +367,6 @@ func run(c *cli.Context) error {
Experimental: c.Bool("daemon.experimental"),
RegistryType: registryType,
},
BaseImageRegistry: c.String("docker.baseimageregistry"),
BaseImageUsername: c.String("docker.baseimageusername"),
BaseImagePassword: c.String("docker.baseimagepassword"),
}
if c.Bool("tags.auto") {
+3 -23
View File
@@ -42,7 +42,6 @@ func main() {
assumeRole = getenv("PLUGIN_ASSUME_ROLE")
externalId = getenv("PLUGIN_EXTERNAL_ID")
scanOnPush = parseBoolOrDefault(false, getenv("PLUGIN_SCAN_ON_PUSH"))
idToken = os.Getenv("PLUGIN_OIDC_TOKEN_ID")
)
// set the region
@@ -62,7 +61,7 @@ func main() {
log.Fatal(fmt.Sprintf("error creating aws session: %v", err))
}
svc := getECRClient(sess, assumeRole, externalId, idToken)
svc := getECRClient(sess, assumeRole, externalId)
username, password, defaultRegistry, err := getAuthInfo(svc)
if registry == "" {
@@ -214,30 +213,11 @@ func getenv(key ...string) (s string) {
return
}
func getECRClient(sess *session.Session, role string, externalId string, idToken string) *ecr.ECR {
func getECRClient(sess *session.Session, role string, externalId string) *ecr.ECR {
if role == "" {
return ecr.New(sess)
}
if idToken != "" {
tempFile, err := os.CreateTemp("/tmp", "idToken-*.jwt")
if err != nil {
log.Fatalf("Failed to create temporary file: %v", err)
}
defer tempFile.Close()
if err := os.Chmod(tempFile.Name(), 0600); err != nil {
log.Fatalf("Failed to set file permissions: %v", err)
}
if _, err := tempFile.WriteString(idToken); err != nil {
log.Fatalf("Failed to write ID token to temporary file: %v", err)
}
// Create credentials using the path to the ID token file
creds := stscreds.NewWebIdentityCredentials(sess, role, "", tempFile.Name())
return ecr.New(sess, &aws.Config{Credentials: creds})
} else if externalId != "" {
if externalId != "" {
return ecr.New(sess, &aws.Config{
Credentials: stscreds.NewCredentials(sess, role, func(p *stscreds.AssumeRoleProvider) {
p.ExternalID = &externalId
-165
View File
@@ -1,165 +0,0 @@
package main
import (
"context"
"encoding/base64"
"fmt"
"log"
"os"
"os/exec"
"path"
"strconv"
"strings"
docker "github.com/drone-plugins/drone-docker"
"github.com/drone-plugins/drone-docker/internal/gcp"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type Config struct {
Repo string
Registry string
Password string
WorkloadIdentity bool
Username string
AccessToken string
}
type staticTokenSource struct {
token *oauth2.Token
}
func (s *staticTokenSource) Token() (*oauth2.Token, error) {
return s.token, nil
}
func loadConfig() Config {
// Default username
username := "_json_key"
var config Config
// Load env-file if it exists
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
if err := godotenv.Load(env); err != nil {
log.Fatalf("Error loading .env file: %v", err)
}
}
idToken := getenv("PLUGIN_OIDC_TOKEN_ID")
projectId := getenv("PLUGIN_PROJECT_NUMBER")
poolId := getenv("PLUGIN_POOL_ID")
providerId := getenv("PLUGIN_PROVIDER_ID")
serviceAccountEmail := getenv("PLUGIN_SERVICE_ACCOUNT_EMAIL")
if idToken != "" && projectId != "" && poolId != "" && providerId != "" && serviceAccountEmail != "" {
federalToken, err := gcp.GetFederalToken(idToken, projectId, poolId, providerId)
if err != nil {
logrus.Fatalf("Error (getFederalToken): %s", err)
}
accessToken, err := gcp.GetGoogleCloudAccessToken(federalToken, serviceAccountEmail)
if err != nil {
logrus.Fatalf("Error (getGoogleCloudAccessToken): %s", err)
}
config.AccessToken = accessToken
} else {
password := getenv(
"PLUGIN_JSON_KEY",
"GCR_JSON_KEY",
"GOOGLE_CREDENTIALS",
"TOKEN",
)
config.WorkloadIdentity = parseBoolOrDefault(false, getenv("PLUGIN_WORKLOAD_IDENTITY"))
config.Username, config.Password = setUsernameAndPassword(username, password, config.WorkloadIdentity)
}
location := getenv("PLUGIN_LOCATION")
repo := getenv("PLUGIN_REPO")
registry := getenv("PLUGIN_REGISTRY")
if registry == "" {
registry = fmt.Sprintf("%s-docker.pkg.dev", location)
}
if !strings.HasPrefix(repo, registry) {
repo = path.Join(registry, repo)
}
config.Repo = repo
config.Registry = registry
return config
}
func main() {
config := loadConfig()
if config.AccessToken != "" {
os.Setenv("ACCESS_TOKEN", config.AccessToken)
} else if config.Username != "" && config.Password != "" {
os.Setenv("DOCKER_USERNAME", config.Username)
os.Setenv("DOCKER_PASSWORD", config.Password)
}
os.Setenv("PLUGIN_REPO", config.Repo)
os.Setenv("PLUGIN_REGISTRY", config.Registry)
// invoke the base docker plugin binary
cmd := exec.Command(docker.GetDroneDockerExecCmd())
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
logrus.Fatal(err)
}
}
func getOauthToken(data []byte) (s string) {
scopes := []string{
"https://www.googleapis.com/auth/cloud-platform",
}
ctx := context.Background()
credentials, err := google.CredentialsFromJSON(ctx, data, scopes...)
if err == nil {
token, err := credentials.TokenSource.Token()
if err == nil {
return token.AccessToken
}
}
return
}
func setUsernameAndPassword(user string, pass string, workloadIdentity bool) (u string, p string) {
// decode the token if base64 encoded
decoded, err := base64.StdEncoding.DecodeString(pass)
if err == nil {
pass = string(decoded)
}
// get oauth token and set username if using workload identity
if workloadIdentity {
data := []byte(pass)
pass = getOauthToken(data)
user = "oauth2accesstoken"
}
return user, pass
}
func parseBoolOrDefault(defaultValue bool, s string) (result bool) {
var err error
result, err = strconv.ParseBool(s)
if err != nil {
result = defaultValue
}
return
}
func getenv(key ...string) (s string) {
for _, k := range key {
s = os.Getenv(k)
if s != "" {
return
}
}
return
}
+78 -4
View File
@@ -3,6 +3,7 @@ package main
import (
"context"
"encoding/base64"
"fmt"
"log"
"os"
"os/exec"
@@ -11,11 +12,14 @@ import (
"strings"
docker "github.com/drone-plugins/drone-docker"
"github.com/drone-plugins/drone-docker/internal/gcp"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/iamcredentials/v1"
"google.golang.org/api/option"
"google.golang.org/api/sts/v1"
)
type Config struct {
@@ -24,9 +28,18 @@ type Config struct {
Password string
WorkloadIdentity bool
Username string
RegistryType string
AccessToken string
}
type staticTokenSource struct {
token *oauth2.Token
}
func (s *staticTokenSource) Token() (*oauth2.Token, error) {
return s.token, nil
}
func loadConfig() Config {
// Default username
username := "_json_key"
@@ -46,11 +59,11 @@ func loadConfig() Config {
serviceAccountEmail := getenv("PLUGIN_SERVICE_ACCOUNT_EMAIL")
if idToken != "" && projectId != "" && poolId != "" && providerId != "" && serviceAccountEmail != "" {
federalToken, err := gcp.GetFederalToken(idToken, projectId, poolId, providerId)
federalToken, err := getFederalToken(idToken, projectId, poolId, providerId)
if err != nil {
logrus.Fatalf("Error (getFederalToken): %s", err)
}
accessToken, err := gcp.GetGoogleCloudAccessToken(federalToken, serviceAccountEmail)
accessToken, err := getGoogleCloudAccessToken(federalToken, serviceAccountEmail)
if err != nil {
logrus.Fatalf("Error (getGoogleCloudAccessToken): %s", err)
}
@@ -66,7 +79,9 @@ func loadConfig() Config {
config.Username, config.Password = setUsernameAndPassword(username, password, config.WorkloadIdentity)
}
location := getenv("PLUGIN_LOCATION")
repo := getenv("PLUGIN_REPO")
registryType := getenv("PLUGIN_REGISTRY_TYPE")
if registryType == "" {
registryType = "GCR"
@@ -74,7 +89,17 @@ func loadConfig() Config {
registry := getenv("PLUGIN_REGISTRY")
if registry == "" {
registry = "gcr.io"
switch registryType {
case "GCR":
registry = "gcr.io"
case "GAR":
if location == "" {
logrus.Fatalf("Error: For REGISTRY_TYPE of GAR, LOCATION must be set")
}
registry = fmt.Sprintf("%s-docker.pkg.dev", location)
default:
logrus.Fatalf("Unsupported registry type: %s", registryType)
}
}
if !strings.HasPrefix(repo, registry) {
@@ -82,6 +107,7 @@ func loadConfig() Config {
}
config.Repo = repo
config.Registry = registry
config.RegistryType = registryType
return config
}
@@ -92,10 +118,12 @@ func main() {
} else if config.Username != "" && config.Password != "" {
os.Setenv("DOCKER_USERNAME", config.Username)
os.Setenv("DOCKER_PASSWORD", config.Password)
os.Setenv("", strconv.FormatBool(config.WorkloadIdentity))
}
os.Setenv("PLUGIN_REPO", config.Repo)
os.Setenv("PLUGIN_REGISTRY", config.Registry)
os.Setenv("PLUGIN_REGISTRY_TYPE", config.RegistryType)
// invoke the base docker plugin binary
cmd := exec.Command(docker.GetDroneDockerExecCmd())
@@ -156,3 +184,49 @@ func getenv(key ...string) (s string) {
}
return
}
func getFederalToken(idToken, projectNumber, poolId, providerId string) (string, error) {
ctx := context.Background()
stsService, err := sts.NewService(ctx, option.WithoutAuthentication())
if err != nil {
return "", err
}
audience := fmt.Sprintf("//iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/%s/providers/%s", projectNumber, poolId, providerId)
tokenRequest := &sts.GoogleIdentityStsV1ExchangeTokenRequest{
GrantType: "urn:ietf:params:oauth:grant-type:token-exchange",
SubjectToken: idToken,
Audience: audience,
Scope: "https://www.googleapis.com/auth/cloud-platform",
RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
SubjectTokenType: "urn:ietf:params:oauth:token-type:id_token",
}
tokenResponse, err := stsService.V1.Token(tokenRequest).Do()
if err != nil {
return "", err
}
return tokenResponse.AccessToken, nil
}
func getGoogleCloudAccessToken(federatedToken string, serviceAccountEmail string) (string, error) {
ctx := context.Background()
tokenSource := &staticTokenSource{
token: &oauth2.Token{AccessToken: federatedToken},
}
service, err := iamcredentials.NewService(ctx, option.WithTokenSource(tokenSource))
if err != nil {
return "", err
}
name := "projects/-/serviceAccounts/" + serviceAccountEmail
rb := &iamcredentials.GenerateAccessTokenRequest{
Scope: []string{"https://www.googleapis.com/auth/cloud-platform"},
}
resp, err := service.Projects.ServiceAccounts.GenerateAccessToken(name, rb).Do()
if err != nil {
return "", err
}
return resp.AccessToken, nil
}
+7 -63
View File
@@ -10,7 +10,6 @@ import (
"strings"
"time"
"github.com/drone-plugins/drone-docker/internal/docker"
"github.com/drone-plugins/drone-plugin-lib/drone"
)
@@ -76,16 +75,13 @@ type (
// Plugin defines the Docker plugin parameters.
Plugin struct {
Login Login // Docker login configuration
Build Build // Docker build configuration
Daemon Daemon // Docker daemon configuration
Dryrun bool // Docker push is skipped
Cleanup bool // Docker purge is enabled
CardPath string // Card path to write file to
ArtifactFile string // Artifact path to write file to
BaseImageRegistry string // Docker registry to pull base image
BaseImageUsername string // Docker registry username to pull base image
BaseImagePassword string // Docker registry password to pull base image
Login Login // Docker login configuration
Build Build // Docker build configuration
Daemon Daemon // Docker daemon configuration
Dryrun bool // Docker push is skipped
Cleanup bool // Docker purge is enabled
CardPath string // Card path to write file to
ArtifactFile string // Artifact path to write file to
}
Card []struct {
@@ -164,29 +160,6 @@ func (p Plugin) Exec() error {
}
}
// instead of writing to config file directly, using docker's login func
// is better to integrate with various credential helpers,
// it also handles different registry specific logic in a better way,
// as opposed to config write where different registries need to be addressed differently.
// It handles any changes in the authentication process across different Docker versions.
if p.BaseImagePassword != "" {
var baseConnectorLogin Login
baseConnectorLogin.Registry = p.BaseImageRegistry
baseConnectorLogin.Username = p.BaseImageUsername
baseConnectorLogin.Password = p.BaseImagePassword
cmd := commandLogin(baseConnectorLogin)
raw, err := cmd.CombinedOutput()
if err != nil {
out := string(raw)
out = strings.Replace(out, "WARNING! Using --password via the CLI is insecure. Use --password-stdin.", "", -1)
fmt.Println(out)
return fmt.Errorf("Error authenticating base connector: exit status 1")
}
}
// login to the Docker registry
if p.Login.Password != "" {
cmd := commandLogin(p.Login)
@@ -297,35 +270,6 @@ func (p Plugin) Exec() error {
return nil
}
// helper function to set the credentials
func setDockerAuth(username, password, registry, baseImageUsername,
baseImagePassword, baseImageRegistry string) ([]byte, error) {
var credentials []docker.RegistryCredentials
// add only docker registry to the config
dockerConfig := docker.NewConfig()
if password != "" {
pushToRegistryCreds := docker.RegistryCredentials{
Registry: registry,
Username: username,
Password: password,
}
// push registry auth
credentials = append(credentials, pushToRegistryCreds)
}
if baseImageRegistry != "" {
pullFromRegistryCreds := docker.RegistryCredentials{
Registry: baseImageRegistry,
Username: baseImageUsername,
Password: baseImagePassword,
}
// base image registry auth
credentials = append(credentials, pullFromRegistryCreds)
}
// Creates docker config for both the registries used for authentication
return dockerConfig.CreateDockerConfigJson(credentials)
}
// helper function to create the docker login command.
func commandLogin(login Login) *exec.Cmd {
if login.Email != "" {
-4
View File
@@ -1,4 +0,0 @@
FROM plugins/docker:linux-amd64
ADD release/linux/amd64/drone-gar /bin/
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "/bin/drone-gar"]
-4
View File
@@ -1,4 +0,0 @@
FROM plugins/docker:linux-arm64
ADD release/linux/arm64/drone-gar /bin/
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "/bin/drone-gar"]
-10
View File
@@ -1,10 +0,0 @@
# escape=`
FROM plugins/docker:windows-1809-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone GAR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-gar.exe C:/bin/drone-gar.exe
ENTRYPOINT [ "C:\\bin\\drone-gar.exe" ]
@@ -1,10 +0,0 @@
# escape=`
FROM plugins/docker:windows-ltsc2022-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone GAR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-gar.exe C:/bin/drone-gar.exe
ENTRYPOINT [ "C:\\bin\\drone-gar.exe" ]
-31
View File
@@ -1,31 +0,0 @@
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
variant: v8
-
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809-amd64
platform:
architecture: amd64
os: windows
version: 1809
-
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2022-amd64
platform:
architecture: amd64
os: windows
version: ltsc2022
View File
-8
View File
@@ -1,8 +0,0 @@
This document explains on how to install certain git hooks globally for all repositories in your machine.
Step 1: git clone https://github.com/drone-plugins/drone-docker.git
Step 2: cd git-hooks
Step 3: Run install.sh
"install.sh" script will create .git_template in the user directory and will put the git hook and its dependent scripts in it. Along with the .git_template folder, it will add 2 sections "init" and "hooks boolean" in the .gitconfig file in the same user's root directory.
After running "install.sh" if you create/clone a new git repository then all the hooks will get install automatically for the git repository. In case of existing git repository copy the contents of ~/.git_template/hooks into the .git/hooks directory of existing git repository.
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
#Helper script to be used as a pre-commit hook.
echo "This hook checks for any secrets getting pushed as part of commit. If you feel that scan is false positive. \
Then add the exclusion in .gitleaksignore file. For more info visit: https://github.com/zricethezav/gitleaks"
GIT_LEAKS_PRE_COMMIT=s$(git config --bool hook.pre-commit.gitleak)
echo "INFO: Scanning Commits information for any GIT LEAKS"
gitleaks protect --staged -v --exit-code=100
STATUS=$?
if [ $STATUS = 100 ]; then
echo "WARNING: GIT LEAKS has detected sensitive information in your changes. Please remove them or add them (IF NON-SENSITIVE) in .gitleaksignore file."
else
exit 0
fi
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
#Helper script to be used as a pre-commit hook.
echo "This hook checks for any secrets getting pushed as part of commit. If you feel that scan is false positive. \
Then add the exclusion in .gitleaksignore file. For more info visit: https://github.com/zricethezav/gitleaks"
GIT_LEAKS=$(git config --bool hook.pre-push.gitleaks)
echo "INFO: Scanning Commits information for any GIT LEAKS"
gitleaks detect -s ./ --log-level=debug --log-opts=-1 -v
STATUS=$?
if [ $STATUS != 0 ]; then
echo "WARNING: GIT LEAKS has detected sensitive information in your changes. Please remove them or add them (IF NON-SENSITIVE) in .gitleaksignore file."
exit $STATUS
else
exit 0
fi
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env bash
GL_SCRIPT_PATH="$HOME/.git_template/hooks/git-leaks-pre-commit.sh"
pushd `dirname $0` > /dev/null && cd ../.. && BASEDIR=$(pwd -L) && popd > /dev/null
BASENAME=`basename $0`
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
#Initial commit : diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
GIT_LEAKS_PRE_COMMIT=hook.pre-commit.gitleaks
if [ "`git config $GIT_LEAKS_PRE_COMMIT`" == "false" ]
then
echo -e '\033[0;31m' checking git leaks is disabled - to enable: '\033[0;37m'git config --unset $GIT_LEAKS_PRE_COMMIT '\033[0m'
echo -e '\033[0;34m' checking git leaks ... to enable: '\033[0;37m'git config --add $GIT_LEAKS_PRE_COMMIT true '\033[0m'
else
echo -e '\033[0;34m' checking for git leaks...
[ -f "${GL_SCRIPT_PATH}" ] && . ${GL_SCRIPT_PATH} || echo "ERROR: Hook Script Not Found..." && exit 404
fi
-24
View File
@@ -1,24 +0,0 @@
#!/usr/bin/env bash
GL_SCRIPT_PATH="$HOME/.git_template/hooks/git-leaks.sh"
pushd `dirname $0` > /dev/null && cd ../.. && BASEDIR=$(pwd -L) && popd > /dev/null
BASENAME=`basename $0`
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
#Initial commit : diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
GIT_LEAKS=hook.pre-push.gitleaks
if [ "`git config $GIT_LEAKS`" == "false" ]
then
echo -e '\033[0;31m' checking git leaks is disabled - to enable: '\033[0;37m'git config --unset $GIT_LEAKS '\033[0m'
echo -e '\033[0;34m' checking git leaks ... to enable: '\033[0;37m'git config --add $GIT_LEAKS true '\033[0m'
else
echo -e '\033[0;34m' checking for git leaks...
[ -f "${GL_SCRIPT_PATH}" ] && . ${GL_SCRIPT_PATH} || echo "ERROR: Hook Script Not Found..." && exit 404
fi
-44
View File
@@ -1,44 +0,0 @@
#!/usr/bin/env bash
#Function to check if package is installed or not
#args: $1: Name of the Package
function check_package_installed() {
LOCAL_PACKAGE_NAME=$1
echo "Checking if $LOCAL_PACKAGE_NAME is installed or not..."
brew list $LOCAL_PACKAGE_NAME
if [ "$?" -eq 1 ];then
echo "Installing $LOCAL_PACKAGE_NAME package..."
brew install $LOCAL_PACKAGE_NAME
fi
}
function create_git_template() {
cd $BASEDIR
mkdir -p ~/.git_template/hooks
git config --global init.templatedir ${GIT_TEMPLATE}
git config --global --add $GIT_LEAKS true
git config --global --add $GIT_LEAKS_PRE_COMMIT true
find hooks/ -type f -exec cp "{}" ~/.git_template/hooks \;
#cp -f hooks/* ~/.git_template/hooks
cat ~/.gitconfig
}
GIT_TEMPLATE="~/.git_template"
GIT_LEAKS=hook.pre-push.gitleaks
GIT_LEAKS_PRE_COMMIT=hook.pre-commit.gitleaks
pushd `dirname $0` && BASEDIR=$(pwd -L) && popd
echo This script will install hooks that run scripts that could be updated without notice.
while true; do
read -p "Do you wish to install these hooks?" yn
case $yn in
[Yy]* ) check_package_installed "gitleaks";
break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
create_git_template
+1 -4
View File
@@ -9,7 +9,6 @@ require (
github.com/inhies/go-bytesize v0.0.0-20210819104631-275770b98743
github.com/joho/godotenv v1.3.0
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.2
golang.org/x/oauth2 v0.13.0
)
@@ -18,7 +17,6 @@ require (
cloud.google.com/go/compute v1.23.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/s2a-go v0.1.7 // indirect
@@ -26,7 +24,6 @@ require (
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
@@ -42,4 +39,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
go 1.22.4
go 1.21
-1
View File
@@ -90,7 +90,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-70
View File
@@ -1,70 +0,0 @@
package docker
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
)
const (
v2HubRegistryURL string = "https://registry.hub.docker.com/v2/"
v1RegistryURL string = "https://index.docker.io/v1/" // Default registry
v2RegistryURL string = "https://index.docker.io/v2/" // v2 registry is not supported
)
type (
Auth struct {
Auth string `json:"auth"`
}
Config struct {
Auths map[string]Auth `json:"auths"`
CredHelpers map[string]string `json:"credHelpers,omitempty"`
}
)
type RegistryCredentials struct {
Registry string
Username string
Password string
}
func NewConfig() *Config {
return &Config{
Auths: make(map[string]Auth),
CredHelpers: make(map[string]string),
}
}
func (c *Config) SetAuth(registry, username, password string) {
authBytes := []byte(username + ":" + password)
encodedString := base64.StdEncoding.EncodeToString(authBytes)
c.Auths[registry] = Auth{Auth: encodedString}
}
func (c *Config) SetCredHelper(registry, helper string) {
c.CredHelpers[registry] = helper
}
func (c *Config) CreateDockerConfigJson(credentials []RegistryCredentials) ([]byte, error) {
for _, cred := range credentials {
if cred.Registry != "" {
if cred.Username == "" {
return nil, fmt.Errorf("Username must be specified for registry: %s", cred.Registry)
}
if cred.Password == "" {
return nil, fmt.Errorf("Password must be specified for registry: %s", cred.Registry)
}
c.SetAuth(cred.Registry, cred.Username, cred.Password)
}
}
jsonBytes, err := json.Marshal(c)
if err != nil {
return nil, errors.New("failed to serialize docker config json")
}
return jsonBytes, nil
}
-64
View File
@@ -1,64 +0,0 @@
package docker
import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
const (
RegistryV1 string = "https://index.docker.io/v1/"
RegistryV2 string = "https://index.docker.io/v2/"
RegistryECRPublic string = "public.ecr.aws"
)
func TestConfig(t *testing.T) {
c := NewConfig()
assert.NotNil(t, c.Auths)
assert.NotNil(t, c.CredHelpers)
c.SetAuth(RegistryV1, "test", "password")
expectedAuth := Auth{Auth: "dGVzdDpwYXNzd29yZA=="}
assert.Equal(t, expectedAuth, c.Auths[RegistryV1])
c.SetCredHelper(RegistryECRPublic, "ecr-login")
assert.Equal(t, "ecr-login", c.CredHelpers[RegistryECRPublic])
tempDir, err := ioutil.TempDir("", "docker-config-test")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)
credentials := []RegistryCredentials{
{
Registry: "https://index.docker.io/v1/",
Username: "user1",
Password: "pass1",
},
{
Registry: "gcr.io",
Username: "user2",
Password: "pass2",
},
}
jsonBytes, err := c.CreateDockerConfigJson(credentials)
assert.NoError(t, err)
configPath := filepath.Join(tempDir, "config.json")
err = ioutil.WriteFile(configPath, jsonBytes, 0644)
assert.NoError(t, err)
data, err := ioutil.ReadFile(configPath)
assert.NoError(t, err)
var configFromFile Config
err = json.Unmarshal(data, &configFromFile)
assert.NoError(t, err)
assert.Equal(t, c.Auths, configFromFile.Auths)
assert.Equal(t, c.CredHelpers, configFromFile.CredHelpers)
}
-65
View File
@@ -1,65 +0,0 @@
package gcp
import (
"context"
"fmt"
"golang.org/x/oauth2"
"google.golang.org/api/iamcredentials/v1"
"google.golang.org/api/option"
"google.golang.org/api/sts/v1"
)
type staticTokenSource struct {
token *oauth2.Token
}
func (s *staticTokenSource) Token() (*oauth2.Token, error) {
return s.token, nil
}
func GetFederalToken(idToken, projectNumber, poolId, providerId string) (string, error) {
ctx := context.Background()
stsService, err := sts.NewService(ctx, option.WithoutAuthentication())
if err != nil {
return "", err
}
audience := fmt.Sprintf("//iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/%s/providers/%s", projectNumber, poolId, providerId)
tokenRequest := &sts.GoogleIdentityStsV1ExchangeTokenRequest{
GrantType: "urn:ietf:params:oauth:grant-type:token-exchange",
SubjectToken: idToken,
Audience: audience,
Scope: "https://www.googleapis.com/auth/cloud-platform",
RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
SubjectTokenType: "urn:ietf:params:oauth:token-type:id_token",
}
tokenResponse, err := stsService.V1.Token(tokenRequest).Do()
if err != nil {
return "", err
}
return tokenResponse.AccessToken, nil
}
func GetGoogleCloudAccessToken(federatedToken string, serviceAccountEmail string) (string, error) {
ctx := context.Background()
tokenSource := &staticTokenSource{
token: &oauth2.Token{AccessToken: federatedToken},
}
service, err := iamcredentials.NewService(ctx, option.WithTokenSource(tokenSource))
if err != nil {
return "", err
}
name := "projects/-/serviceAccounts/" + serviceAccountEmail
rb := &iamcredentials.GenerateAccessTokenRequest{
Scope: []string{"https://www.googleapis.com/auth/cloud-platform"},
}
resp, err := service.Projects.ServiceAccounts.GenerateAccessToken(name, rb).Do()
if err != nil {
return "", err
}
return resp.AccessToken, nil
}