From f5313ed2c005e2ad08912b4b76e75ef664784f3d Mon Sep 17 00:00:00 2001 From: Priya Wadhwa Date: Thu, 2 Mar 2023 13:59:25 -0500 Subject: [PATCH] Implement Issuer interface for username and uri Issuer types Signed-off-by: Priya Wadhwa --- pkg/identity/uri/issuer.go | 42 ++++++++++++++++ pkg/identity/uri/issuer_test.go | 71 ++++++++++++++++++++++++++++ pkg/identity/username/issuer.go | 42 ++++++++++++++++ pkg/identity/username/issuer_test.go | 71 ++++++++++++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 pkg/identity/uri/issuer.go create mode 100644 pkg/identity/uri/issuer_test.go create mode 100644 pkg/identity/username/issuer.go create mode 100644 pkg/identity/username/issuer_test.go diff --git a/pkg/identity/uri/issuer.go b/pkg/identity/uri/issuer.go new file mode 100644 index 000000000..a22853b1b --- /dev/null +++ b/pkg/identity/uri/issuer.go @@ -0,0 +1,42 @@ +// Copyright 2023 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package uri + +import ( + "context" + + "github.com/sigstore/fulcio/pkg/identity" +) + +type uriIssuer struct { + issuerURL string +} + +func Issuer(issuerURL string) identity.Issuer { + return &uriIssuer{issuerURL: issuerURL} +} + +func (e *uriIssuer) Authenticate(ctx context.Context, token string) (identity.Principal, error) { + idtoken, err := identity.Authorize(ctx, token) + if err != nil { + return nil, err + } + return PrincipalFromIDToken(ctx, idtoken) +} + +// Match checks if this issuer can authenticate tokens from a given issuer URL +func (e *uriIssuer) Match(ctx context.Context, url string) bool { + return url == e.issuerURL +} diff --git a/pkg/identity/uri/issuer_test.go b/pkg/identity/uri/issuer_test.go new file mode 100644 index 000000000..c90f1cf76 --- /dev/null +++ b/pkg/identity/uri/issuer_test.go @@ -0,0 +1,71 @@ +// Copyright 2023 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package uri + +import ( + "context" + "testing" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestIssuer(t *testing.T) { + ctx := context.Background() + url := "test-issuer-url" + issuer := Issuer(url) + + // test the Match function + t.Run("match", func(t *testing.T) { + if matches := issuer.Match(ctx, url); !matches { + t.Fatal("expected url to match but it doesn't") + } + if matches := issuer.Match(ctx, "some-other-url"); matches { + t.Fatal("expected match to fail but it didn't") + } + }) + + t.Run("authenticate", func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: "https://accounts.example.com", + Subject: "https://example.com/users/1", + } + + cfg := &config.FulcioConfig{ + OIDCIssuers: map[string]config.OIDCIssuer{ + "https://accounts.example.com": { + IssuerURL: "https://accounts.example.com", + ClientID: "sigstore", + SubjectDomain: "https://example.com", + Type: config.IssuerTypeURI, + }, + }, + } + ctx := config.With(context.Background(), cfg) + + identity.Authorize = func(_ context.Context, _ string) (*oidc.IDToken, error) { + return token, nil + } + principal, err := issuer.Authenticate(ctx, "token") + if err != nil { + t.Fatal(err) + } + + if principal.Name(ctx) != "https://example.com/users/1" { + t.Fatalf("got unexpected name %s", principal.Name(ctx)) + } + }) +} diff --git a/pkg/identity/username/issuer.go b/pkg/identity/username/issuer.go new file mode 100644 index 000000000..0a473c9da --- /dev/null +++ b/pkg/identity/username/issuer.go @@ -0,0 +1,42 @@ +// Copyright 2023 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package username + +import ( + "context" + + "github.com/sigstore/fulcio/pkg/identity" +) + +type usernameIssuer struct { + issuerURL string +} + +func Issuer(issuerURL string) identity.Issuer { + return &usernameIssuer{issuerURL: issuerURL} +} + +func (e *usernameIssuer) Authenticate(ctx context.Context, token string) (identity.Principal, error) { + idtoken, err := identity.Authorize(ctx, token) + if err != nil { + return nil, err + } + return PrincipalFromIDToken(ctx, idtoken) +} + +// Match checks if this issuer can authenticate tokens from a given issuer URL +func (e *usernameIssuer) Match(ctx context.Context, url string) bool { + return url == e.issuerURL +} diff --git a/pkg/identity/username/issuer_test.go b/pkg/identity/username/issuer_test.go new file mode 100644 index 000000000..18df7683d --- /dev/null +++ b/pkg/identity/username/issuer_test.go @@ -0,0 +1,71 @@ +// Copyright 2023 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package username + +import ( + "context" + "testing" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestIssuer(t *testing.T) { + ctx := context.Background() + url := "test-issuer-url" + issuer := Issuer(url) + + // test the Match function + t.Run("match", func(t *testing.T) { + if matches := issuer.Match(ctx, url); !matches { + t.Fatal("expected url to match but it doesn't") + } + if matches := issuer.Match(ctx, "some-other-url"); matches { + t.Fatal("expected match to fail but it didn't") + } + }) + + t.Run("authenticate", func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: "https://accounts.example.com", + Subject: "alice", + } + + cfg := &config.FulcioConfig{ + OIDCIssuers: map[string]config.OIDCIssuer{ + "https://accounts.example.com": { + IssuerURL: "https://accounts.example.com", + ClientID: "sigstore", + SubjectDomain: "example.com", + Type: config.IssuerTypeUsername, + }, + }, + } + ctx := config.With(context.Background(), cfg) + + identity.Authorize = func(_ context.Context, _ string) (*oidc.IDToken, error) { + return token, nil + } + principal, err := issuer.Authenticate(ctx, "token") + if err != nil { + t.Fatal(err) + } + + if principal.Name(ctx) != "alice" { + t.Fatalf("got unexpected name %s", principal.Name(ctx)) + } + }) +}