Skip to content

Commit

Permalink
pass the token via authorization header
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Sep 20, 2021
1 parent 813fd9d commit 295f45a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 48 deletions.
13 changes: 7 additions & 6 deletions action/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ interface GetTokenParams {
}

interface GetTokenPayload {
github_token?: string;
id_token?: string;
api_url: string;
repository: string;
sha: string;
Expand Down Expand Up @@ -80,17 +78,20 @@ export async function assumeRole(params: GetTokenParams) {
repository: GITHUB_REPOSITORY,
sha: GITHUB_SHA,
};
const headers: { [name: string]: string } = {};

let token: string;
if (isIdTokenAvailable()) {
payload.id_token = await core.getIDToken(params.audience);
token = await core.getIDToken(params.audience);
} else {
validateGitHubToken(params.githubToken);
payload.github_token = params.githubToken;
token = params.githubToken;
}
headers["Authorization"] = `Bearer ${token}`;

const client = new http.HttpClient("actions-github-app-token");
const result = await client.postJson<GetTokenResult | GetTokenError>(params.providerEndpoint, payload);
if (result.statusCode !== 200) {
const result = await client.postJson<GetTokenResult | GetTokenError>(params.providerEndpoint, payload, headers);
if (result.statusCode !== http.HttpCodes.OK) {
const resp = result.result as GetTokenError;
core.setFailed(resp.message);
return;
Expand Down
77 changes: 47 additions & 30 deletions provider/github-app-token/github-app-token.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,9 @@ func NewHandler() (*Handler, error) {
}

type requestBody struct {
GitHubToken string `json:"github_token,omitempty"`
IDToken string `json:"id_token,omitempty"`
Repository string `json:"repository"`
SHA string `json:"sha"`
APIURL string `json:"api_url"`
Repository string `json:"repository"`
SHA string `json:"sha"`
APIURL string `json:"api_url"`
}

type responseBody struct {
Expand Down Expand Up @@ -131,8 +129,13 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
})
return
}
token, err := h.getAuthToken(r.Header)
if err != nil {
h.handleError(w, r, err)
return
}

resp, err := h.handle(ctx, payload)
resp, err := h.handle(ctx, token, payload)
if err != nil {
h.handleError(w, r, err)
return
Expand All @@ -144,34 +147,32 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}

func (h *Handler) handle(ctx context.Context, req *requestBody) (*responseBody, error) {
func (h *Handler) handle(ctx context.Context, token string, req *requestBody) (*responseBody, error) {
if err := h.github.ValidateAPIURL(req.APIURL); err != nil {
return nil, &validationError{
message: err.Error(),
}
}
if req.IDToken != "" {
_, err := h.github.ParseIDToken(ctx, req.IDToken)

// authorize the request
var owner, repo string
if id, err := h.github.ParseIDToken(ctx, token); err == nil {
owner, repo, err = splitOwnerRepo(id.Repository)
if err != nil {
return nil, &validationError{
message: "invalid JSON Web Token",
}
return nil, err
}
} else if req.GitHubToken != "" {
err := h.validateGitHubToken(ctx, req)
} else {
err := h.validateGitHubToken(ctx, token, req)
if err != nil {
return nil, err
}
} else {
return nil, &validationError{
message: "github_token or id_token is required",
owner, repo, err = splitOwnerRepo(req.Repository)
if err != nil {
return nil, err
}
}

owner, repo, err := splitOwnerRepo(req.Repository)
if err != nil {
return nil, err
}
// issue a new access token
inst, err := h.github.GetReposInstallation(ctx, owner, repo)
if err != nil {
var ghErr *github.ErrUnexpectedStatusCode
Expand All @@ -189,15 +190,15 @@ func (h *Handler) handle(ctx context.Context, req *requestBody) (*responseBody,
}
return nil, fmt.Errorf("failed to get resp's installation: %w", err)
}
token, err := h.github.CreateAppAccessToken(ctx, inst.ID, &github.CreateAppAccessTokenRequest{
resp, err := h.github.CreateAppAccessToken(ctx, inst.ID, &github.CreateAppAccessTokenRequest{
Repositories: []string{repo},
})
if err != nil {
return nil, fmt.Errorf("failed create access token: %w", err)
}

return &responseBody{
GitHubToken: token.Token,
GitHubToken: resp.Token,
}, nil
}

Expand Down Expand Up @@ -243,15 +244,31 @@ func (h *Handler) handleMethodNotAllowed(w http.ResponseWriter) {
w.Write(data)
}

func (h *Handler) validateGitHubToken(ctx context.Context, req *requestBody) error {
func (h *Handler) getAuthToken(header http.Header) (string, error) {
const prefix = "Bearer "
v := header.Get("Authorization")
if len(v) < len(prefix) {
return "", &validationError{
message: "invalid Authorization header",
}
}
if !strings.EqualFold(v[:len(prefix)], prefix) {
return "", &validationError{
message: "invalid Authorization header",
}
}
return v[len(prefix):], nil
}

func (h *Handler) validateGitHubToken(ctx context.Context, token string, req *requestBody) error {
// early check of the token prefix
// ref. https://github.blog/changelog/2021-03-31-authentication-token-format-updates-are-generally-available/
if len(req.GitHubToken) < 4 {
if len(token) < 4 {
return &validationError{
message: "GITHUB_TOKEN has invalid format",
}
}
switch req.GitHubToken[:4] {
switch token[:4] {
case "ghp_":
// Personal Access Tokens
return &validationError{
Expand Down Expand Up @@ -281,9 +298,9 @@ func (h *Handler) validateGitHubToken(ctx context.Context, req *requestBody) err
message: "GITHUB_TOKEN looks like Personal Access Token. `github-token` must be `${{ github.token }}` or `${{ secrets.GITHUB_TOKEN }}`.",
}
}
resp, err := h.updateCommitStatus(ctx, req, &github.CreateStatusRequest{
resp, err := h.updateCommitStatus(ctx, token, req, &github.CreateStatusRequest{
State: github.CommitStateSuccess,
Description: "valid github token",
Description: "valid GitHub token",
Context: commitStatusContext,
})
if err != nil {
Expand Down Expand Up @@ -318,10 +335,10 @@ func splitOwnerRepo(fullname string) (owner, repo string, err error) {
return
}

func (h *Handler) updateCommitStatus(ctx context.Context, req *requestBody, status *github.CreateStatusRequest) (*github.CreateStatusResponse, error) {
func (h *Handler) updateCommitStatus(ctx context.Context, token string, req *requestBody, status *github.CreateStatusRequest) (*github.CreateStatusResponse, error) {
owner, repo, err := splitOwnerRepo(req.Repository)
if err != nil {
return nil, err
}
return h.github.CreateStatus(ctx, req.GitHubToken, owner, repo, req.SHA, status)
return h.github.CreateStatus(ctx, token, owner, repo, req.SHA, status)
}
21 changes: 9 additions & 12 deletions provider/github-app-token/github-app-token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,9 @@ func TestValidateGitHubToken(t *testing.T) {
},
},
}
err := h.validateGitHubToken(context.Background(), &requestBody{
GitHubToken: "ghs_dummyGitHubToken",
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
err := h.validateGitHubToken(context.Background(), "ghs_dummyGitHubToken", &requestBody{
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
})
if err != nil {
t.Error(err)
Expand All @@ -97,10 +96,9 @@ func TestValidateGitHubToken_PermissionError(t *testing.T) {
},
},
}
err := h.validateGitHubToken(context.Background(), &requestBody{
GitHubToken: "ghs_dummyGitHubToken",
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
err := h.validateGitHubToken(context.Background(), "ghs_dummyGitHubToken", &requestBody{
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
})
if err == nil {
t.Error("want error, but not")
Expand Down Expand Up @@ -129,10 +127,9 @@ func TestValidateGitHubToken_InvalidCreator(t *testing.T) {
},
},
}
err := h.validateGitHubToken(context.Background(), &requestBody{
GitHubToken: "ghs_dummyGitHubToken",
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
err := h.validateGitHubToken(context.Background(), "ghs_dummyGitHubToken", &requestBody{
Repository: "fuller-inc/actions-aws-assume-role",
SHA: "e3a45c6c16c1464826b36a598ff39e6cc98c4da4",
})
if err == nil {
t.Error("want error, but not")
Expand Down

0 comments on commit 295f45a

Please sign in to comment.