From 5c910bbea0cca5dd88866e5c9ef3ab137c75c387 Mon Sep 17 00:00:00 2001 From: Tommaso Sardelli Date: Wed, 19 Jul 2023 18:19:18 +0200 Subject: [PATCH 1/2] chore: revert "fix: refresh token only once for all concurrent requests" This reverts commit 4b5f1d52894625db361d4208ea4303c27787a7ae. --- server/refreshhandlers.go | 205 ++++++++++++----------------- storage/kubernetes/lock.go | 124 ----------------- storage/kubernetes/storage.go | 9 -- storage/kubernetes/storage_test.go | 104 +-------------- 4 files changed, 85 insertions(+), 357 deletions(-) delete mode 100644 storage/kubernetes/lock.go diff --git a/server/refreshhandlers.go b/server/refreshhandlers.go index ecfda137f0..0c9b1393d3 100644 --- a/server/refreshhandlers.go +++ b/server/refreshhandlers.go @@ -28,10 +28,6 @@ type refreshError struct { desc string } -func (r *refreshError) Error() string { - return fmt.Sprintf("refresh token error: status %d, %q %s", r.code, r.msg, r.desc) -} - func newInternalServerError() *refreshError { return &refreshError{msg: errInvalidRequest, desc: "", code: http.StatusInternalServerError} } @@ -64,23 +60,10 @@ func (s *Server) extractRefreshTokenFromRequest(r *http.Request) (*internal.Refr return token, nil } -type refreshContext struct { - storageToken *storage.RefreshToken - requestToken *internal.RefreshToken - - connector Connector - connectorData []byte - - scopes []string -} - // getRefreshTokenFromStorage checks that refresh token is valid and exists in the storage and gets its info -func (s *Server) getRefreshTokenFromStorage(clientID string, token *internal.RefreshToken) (*refreshContext, *refreshError) { - refreshCtx := refreshContext{requestToken: token} - +func (s *Server) getRefreshTokenFromStorage(clientID string, token *internal.RefreshToken) (*storage.RefreshToken, *refreshError) { invalidErr := newBadRequestError("Refresh token is invalid or has already been claimed by another client.") - // Get RefreshToken refresh, err := s.storage.GetRefresh(token.RefreshId) if err != nil { if err != storage.ErrNotFound { @@ -120,31 +103,7 @@ func (s *Server) getRefreshTokenFromStorage(clientID string, token *internal.Ref return nil, expiredErr } - refreshCtx.storageToken = &refresh - - // Get Connector - refreshCtx.connector, err = s.getConnector(refresh.ConnectorID) - if err != nil { - s.logger.Errorf("connector with ID %q not found: %v", refresh.ConnectorID, err) - return nil, newInternalServerError() - } - - // Get Connector Data - session, err := s.storage.GetOfflineSessions(refresh.Claims.UserID, refresh.ConnectorID) - switch { - case err != nil: - if err != storage.ErrNotFound { - s.logger.Errorf("failed to get offline session: %v", err) - return nil, newInternalServerError() - } - case len(refresh.ConnectorData) > 0: - // Use the old connector data if it exists, should be deleted once used - refreshCtx.connectorData = refresh.ConnectorData - default: - refreshCtx.connectorData = session.ConnectorData - } - - return &refreshCtx, nil + return &refresh, nil } func (s *Server) getRefreshScopes(r *http.Request, refresh *storage.RefreshToken) ([]string, *refreshError) { @@ -179,23 +138,59 @@ func (s *Server) getRefreshScopes(r *http.Request, refresh *storage.RefreshToken return requestedScopes, nil } -func (s *Server) refreshWithConnector(ctx context.Context, rCtx *refreshContext, ident connector.Identity) (connector.Identity, *refreshError) { +func (s *Server) refreshWithConnector(ctx context.Context, token *internal.RefreshToken, refresh *storage.RefreshToken, scopes []string) (connector.Identity, *refreshError) { + var connectorData []byte + + session, err := s.storage.GetOfflineSessions(refresh.Claims.UserID, refresh.ConnectorID) + switch { + case err != nil: + if err != storage.ErrNotFound { + s.logger.Errorf("failed to get offline session: %v", err) + return connector.Identity{}, newInternalServerError() + } + case len(refresh.ConnectorData) > 0: + // Use the old connector data if it exists, should be deleted once used + connectorData = refresh.ConnectorData + default: + connectorData = session.ConnectorData + } + + conn, err := s.getConnector(refresh.ConnectorID) + if err != nil { + s.logger.Errorf("connector with ID %q not found: %v", refresh.ConnectorID, err) + return connector.Identity{}, newInternalServerError() + } + + ident := connector.Identity{ + UserID: refresh.Claims.UserID, + Username: refresh.Claims.Username, + PreferredUsername: refresh.Claims.PreferredUsername, + Email: refresh.Claims.Email, + EmailVerified: refresh.Claims.EmailVerified, + Groups: refresh.Claims.Groups, + ConnectorData: connectorData, + } + + // user's token was previously updated by a connector and is allowed to reuse + // it is excessive to refresh identity in upstream + if s.refreshTokenPolicy.AllowedToReuse(refresh.LastUsed) && token.Token == refresh.ObsoleteToken { + return ident, nil + } + // Can the connector refresh the identity? If so, attempt to refresh the data // in the connector. // // TODO(ericchiang): We may want a strict mode where connectors that don't implement // this interface can't perform refreshing. - if refreshConn, ok := rCtx.connector.Connector.(connector.RefreshConnector); ok { - s.logger.Debugf("connector data before refresh: %s", ident.ConnectorData) - - newIdent, err := refreshConn.Refresh(ctx, parseScopes(rCtx.scopes), ident) + if refreshConn, ok := conn.Connector.(connector.RefreshConnector); ok { + newIdent, err := refreshConn.Refresh(ctx, parseScopes(scopes), ident) if err != nil { s.logger.Errorf("failed to refresh identity: %v", err) - return ident, newInternalServerError() + return connector.Identity{}, newInternalServerError() } - - return newIdent, nil + ident = newIdent } + return ident, nil } @@ -205,14 +200,8 @@ func (s *Server) updateOfflineSession(refresh *storage.RefreshToken, ident conne if old.Refresh[refresh.ClientID].ID != refresh.ID { return old, errors.New("refresh token invalid") } - old.Refresh[refresh.ClientID].LastUsed = lastUsed - if len(ident.ConnectorData) > 0 { - old.ConnectorData = ident.ConnectorData - } - - s.logger.Debugf("saved connector data: %s %s", ident.UserID, ident.ConnectorData) - + old.ConnectorData = ident.ConnectorData return old, nil } @@ -228,74 +217,33 @@ func (s *Server) updateOfflineSession(refresh *storage.RefreshToken, ident conne } // updateRefreshToken updates refresh token and offline session in the storage -func (s *Server) updateRefreshToken(ctx context.Context, rCtx *refreshContext) (*internal.RefreshToken, connector.Identity, *refreshError) { - var rerr *refreshError - - newToken := &internal.RefreshToken{ - Token: rCtx.requestToken.Token, - RefreshId: rCtx.requestToken.RefreshId, +func (s *Server) updateRefreshToken(token *internal.RefreshToken, refresh *storage.RefreshToken, ident connector.Identity) (*internal.RefreshToken, *refreshError) { + newToken := token + if s.refreshTokenPolicy.RotationEnabled() { + newToken = &internal.RefreshToken{ + RefreshId: refresh.ID, + Token: storage.NewID(), + } } lastUsed := s.now() - ident := connector.Identity{ - UserID: rCtx.storageToken.Claims.UserID, - Username: rCtx.storageToken.Claims.Username, - PreferredUsername: rCtx.storageToken.Claims.PreferredUsername, - Email: rCtx.storageToken.Claims.Email, - EmailVerified: rCtx.storageToken.Claims.EmailVerified, - Groups: rCtx.storageToken.Claims.Groups, - ConnectorData: rCtx.connectorData, - } - refreshTokenUpdater := func(old storage.RefreshToken) (storage.RefreshToken, error) { - rotationEnabled := s.refreshTokenPolicy.RotationEnabled() - reusingAllowed := s.refreshTokenPolicy.AllowedToReuse(old.LastUsed) - - switch { - case !rotationEnabled && reusingAllowed: - // If rotation is disabled and the offline session was updated not so long ago - skip further actions. - return old, nil - - case rotationEnabled && reusingAllowed: - if old.Token != rCtx.requestToken.Token && old.ObsoleteToken != rCtx.requestToken.Token { + if s.refreshTokenPolicy.RotationEnabled() { + if old.Token != token.Token { + if s.refreshTokenPolicy.AllowedToReuse(old.LastUsed) && old.ObsoleteToken == token.Token { + newToken.Token = old.Token + // Do not update last used time for offline session if token is allowed to be reused + lastUsed = old.LastUsed + return old, nil + } return old, errors.New("refresh token claimed twice") } - // Return previously generated token for all requests with an obsolete tokens - if old.ObsoleteToken == rCtx.requestToken.Token { - newToken.Token = old.Token - } - - // Do not update last used time for offline session if token is allowed to be reused - lastUsed = old.LastUsed - ident.ConnectorData = nil - return old, nil - - case rotationEnabled && !reusingAllowed: - if old.Token != rCtx.requestToken.Token { - return old, errors.New("refresh token claimed twice") - } - - // Issue new refresh token old.ObsoleteToken = old.Token - newToken.Token = storage.NewID() } old.Token = newToken.Token - old.LastUsed = lastUsed - - // ConnectorData has been moved to OfflineSession - old.ConnectorData = []byte{} - - // Call only once if there is a request which is not in the reuse interval. - // This is required to avoid multiple calls to the external IdP for concurrent requests. - // Dex will call the connector's Refresh method only once if request is not in reuse interval. - ident, rerr = s.refreshWithConnector(ctx, rCtx, ident) - if rerr != nil { - return old, rerr - } - // Update the claims of the refresh token. // // UserID intentionally ignored for now. @@ -304,23 +252,26 @@ func (s *Server) updateRefreshToken(ctx context.Context, rCtx *refreshContext) ( old.Claims.Email = ident.Email old.Claims.EmailVerified = ident.EmailVerified old.Claims.Groups = ident.Groups + old.LastUsed = lastUsed + // ConnectorData has been moved to OfflineSession + old.ConnectorData = []byte{} return old, nil } // Update refresh token in the storage. - err := s.storage.UpdateRefreshToken(rCtx.storageToken.ID, refreshTokenUpdater) + err := s.storage.UpdateRefreshToken(refresh.ID, refreshTokenUpdater) if err != nil { s.logger.Errorf("failed to update refresh token: %v", err) - return nil, ident, newInternalServerError() + return nil, newInternalServerError() } - rerr = s.updateOfflineSession(rCtx.storageToken, ident, lastUsed) + rerr := s.updateOfflineSession(refresh, ident, lastUsed) if rerr != nil { - return nil, ident, rerr + return nil, rerr } - return newToken, ident, nil + return newToken, nil } // handleRefreshToken handles a refresh token request https://tools.ietf.org/html/rfc6749#section-6 @@ -332,19 +283,19 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie return } - rCtx, rerr := s.getRefreshTokenFromStorage(client.ID, token) + refresh, rerr := s.getRefreshTokenFromStorage(client.ID, token) if rerr != nil { s.refreshTokenErrHelper(w, rerr) return } - rCtx.scopes, rerr = s.getRefreshScopes(r, rCtx.storageToken) + scopes, rerr := s.getRefreshScopes(r, refresh) if rerr != nil { s.refreshTokenErrHelper(w, rerr) return } - newToken, ident, rerr := s.updateRefreshToken(r.Context(), rCtx) + ident, rerr := s.refreshWithConnector(r.Context(), token, refresh, scopes) if rerr != nil { s.refreshTokenErrHelper(w, rerr) return @@ -359,20 +310,26 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie Groups: ident.Groups, } - accessToken, err := s.newAccessToken(client.ID, claims, rCtx.scopes, rCtx.storageToken.Nonce, rCtx.storageToken.ConnectorID) + accessToken, err := s.newAccessToken(client.ID, claims, scopes, refresh.Nonce, refresh.ConnectorID) if err != nil { s.logger.Errorf("failed to create new access token: %v", err) s.refreshTokenErrHelper(w, newInternalServerError()) return } - idToken, expiry, err := s.newIDToken(client.ID, claims, rCtx.scopes, rCtx.storageToken.Nonce, accessToken, "", rCtx.storageToken.ConnectorID) + idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, refresh.Nonce, accessToken, "", refresh.ConnectorID) if err != nil { s.logger.Errorf("failed to create ID token: %v", err) s.refreshTokenErrHelper(w, newInternalServerError()) return } + newToken, rerr := s.updateRefreshToken(token, refresh, ident) + if rerr != nil { + s.refreshTokenErrHelper(w, rerr) + return + } + rawNewToken, err := internal.Marshal(newToken) if err != nil { s.logger.Errorf("failed to marshal refresh token: %v", err) diff --git a/storage/kubernetes/lock.go b/storage/kubernetes/lock.go deleted file mode 100644 index 798c1f161f..0000000000 --- a/storage/kubernetes/lock.go +++ /dev/null @@ -1,124 +0,0 @@ -package kubernetes - -import ( - "fmt" - "time" -) - -const ( - lockAnnotation = "dexidp.com/resource-lock" - lockTimeFormat = time.RFC3339 -) - -var ( - lockTimeout = 10 * time.Second - lockCheckPeriod = 100 * time.Millisecond -) - -// refreshTokenLock is an implementation of annotation-based optimistic locking. -// -// Refresh token contains data to refresh identity in external authentication system. -// There is a requirement that refresh should be called only once because of several reasons: -// * Some of OIDC providers could use the refresh token rotation feature which requires calling refresh only once. -// * Providers can limit the rate of requests to the token endpoint, which will lead to the error -// in case of many concurrent requests. -type refreshTokenLock struct { - cli *client - waitingState bool -} - -func newRefreshTokenLock(cli *client) *refreshTokenLock { - return &refreshTokenLock{cli: cli} -} - -func (l *refreshTokenLock) Lock(id string) error { - for i := 0; i <= 60; i++ { - ok, err := l.setLockAnnotation(id) - if err != nil { - return err - } - if !ok { - return nil - } - time.Sleep(lockCheckPeriod) - } - return fmt.Errorf("timeout waiting for refresh token %s lock", id) -} - -func (l *refreshTokenLock) Unlock(id string) { - if l.waitingState { - // Do not need to unlock for waiting goroutines, because the have not set it. - return - } - - r, err := l.cli.getRefreshToken(id) - if err != nil { - l.cli.logger.Debugf("failed to get resource to release lock for refresh token %s: %v", id, err) - return - } - - r.Annotations = nil - err = l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) - if err != nil { - l.cli.logger.Debugf("failed to release lock for refresh token %s: %v", id, err) - } -} - -func (l *refreshTokenLock) setLockAnnotation(id string) (bool, error) { - r, err := l.cli.getRefreshToken(id) - if err != nil { - return false, err - } - - currentTime := time.Now() - lockData := map[string]string{ - lockAnnotation: currentTime.Add(lockTimeout).Format(lockTimeFormat), - } - - val, ok := r.Annotations[lockAnnotation] - if !ok { - if l.waitingState { - return false, nil - } - - r.Annotations = lockData - err := l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) - if err == nil { - return false, nil - } - - if isKubernetesAPIConflictError(err) { - l.waitingState = true - return true, nil - } - return false, err - } - - until, err := time.Parse(lockTimeFormat, val) - if err != nil { - return false, fmt.Errorf("lock annotation value is malformed: %v", err) - } - - if !currentTime.After(until) { - // waiting for the lock to be released - l.waitingState = true - return true, nil - } - - // Lock time is out, lets break the lock and take the advantage - r.Annotations = lockData - - err = l.cli.put(resourceRefreshToken, r.ObjectMeta.Name, r) - if err == nil { - // break lock annotation - return false, nil - } - - l.cli.logger.Debugf("break lock annotation error: %v", err) - if isKubernetesAPIConflictError(err) { - l.waitingState = true - // after breaking error waiting for the lock to be released - return true, nil - } - return false, err -} diff --git a/storage/kubernetes/storage.go b/storage/kubernetes/storage.go index 0979f14ac0..033d3e2356 100644 --- a/storage/kubernetes/storage.go +++ b/storage/kubernetes/storage.go @@ -451,19 +451,11 @@ func (cli *client) DeleteConnector(id string) error { } func (cli *client) UpdateRefreshToken(id string, updater func(old storage.RefreshToken) (storage.RefreshToken, error)) error { - lock := newRefreshTokenLock(cli) - - if err := lock.Lock(id); err != nil { - return err - } - defer lock.Unlock(id) - return retryOnConflict(context.TODO(), func() error { r, err := cli.getRefreshToken(id) if err != nil { return err } - updated, err := updater(toStorageRefreshToken(r)) if err != nil { return err @@ -472,7 +464,6 @@ func (cli *client) UpdateRefreshToken(id string, updater func(old storage.Refres newToken := cli.fromStorageRefreshToken(updated) newToken.ObjectMeta = r.ObjectMeta - return cli.put(resourceRefreshToken, r.ObjectMeta.Name, newToken) }) } diff --git a/storage/kubernetes/storage_test.go b/storage/kubernetes/storage_test.go index d0048506be..828ff472cf 100644 --- a/storage/kubernetes/storage_test.go +++ b/storage/kubernetes/storage_test.go @@ -11,7 +11,6 @@ import ( "path/filepath" "strings" "testing" - "time" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -36,22 +35,19 @@ type StorageTestSuite struct { client *client } -func expandDir(dir string) (string, error) { +func (s *StorageTestSuite) expandDir(dir string) string { dir = strings.Trim(dir, `"`) if strings.HasPrefix(dir, "~/") { homedir, err := os.UserHomeDir() - if err != nil { - return "", err - } + s.Require().NoError(err) dir = filepath.Join(homedir, strings.TrimPrefix(dir, "~/")) } - return dir, nil + return dir } func (s *StorageTestSuite) SetupTest() { - kubeconfigPath, err := expandDir(os.Getenv(kubeconfigPathVariableName)) - s.Require().NoError(err) + kubeconfigPath := s.expandDir(os.Getenv(kubeconfigPathVariableName)) config := Config{ KubeConfigFile: kubeconfigPath, @@ -296,95 +292,3 @@ func TestRetryOnConflict(t *testing.T) { }) } } - -func TestRefreshTokenLock(t *testing.T) { - if os.Getenv(kubeconfigPathVariableName) == "" { - t.Skipf("variable %q not set, skipping kubernetes storage tests\n", kubeconfigPathVariableName) - } - - kubeconfigPath, err := expandDir(os.Getenv(kubeconfigPathVariableName)) - require.NoError(t, err) - - config := Config{ - KubeConfigFile: kubeconfigPath, - } - - logger := &logrus.Logger{ - Out: os.Stderr, - Formatter: &logrus.TextFormatter{DisableColors: true}, - Level: logrus.DebugLevel, - } - - kubeClient, err := config.open(logger, true) - require.NoError(t, err) - - lockCheckPeriod = time.Nanosecond - - // Creating a storage with an existing refresh token and offline session for the user. - id := storage.NewID() - r := storage.RefreshToken{ - ID: id, - Token: "bar", - Nonce: "foo", - ClientID: "client_id", - ConnectorID: "client_secret", - Scopes: []string{"openid", "email", "profile"}, - CreatedAt: time.Now().UTC().Round(time.Millisecond), - LastUsed: time.Now().UTC().Round(time.Millisecond), - Claims: storage.Claims{ - UserID: "1", - Username: "jane", - Email: "jane.doe@example.com", - EmailVerified: true, - Groups: []string{"a", "b"}, - }, - ConnectorData: []byte(`{"some":"data"}`), - } - - err = kubeClient.CreateRefresh(r) - require.NoError(t, err) - - t.Run("Timeout lock error", func(t *testing.T) { - err = kubeClient.UpdateRefreshToken(r.ID, func(r storage.RefreshToken) (storage.RefreshToken, error) { - r.Token = "update-result-1" - err := kubeClient.UpdateRefreshToken(r.ID, func(r storage.RefreshToken) (storage.RefreshToken, error) { - r.Token = "timeout-err" - return r, nil - }) - require.Equal(t, fmt.Errorf("timeout waiting for refresh token %s lock", r.ID), err) - return r, nil - }) - require.NoError(t, err) - - token, err := kubeClient.GetRefresh(r.ID) - require.NoError(t, err) - require.Equal(t, "update-result-1", token.Token) - }) - - t.Run("Break the lock", func(t *testing.T) { - var lockBroken bool - lockTimeout = -time.Hour - - err = kubeClient.UpdateRefreshToken(r.ID, func(r storage.RefreshToken) (storage.RefreshToken, error) { - r.Token = "update-result-2" - if lockBroken { - return r, nil - } - - err := kubeClient.UpdateRefreshToken(r.ID, func(r storage.RefreshToken) (storage.RefreshToken, error) { - r.Token = "should-break-the-lock-and-finish-updating" - return r, nil - }) - require.NoError(t, err) - - lockBroken = true - return r, nil - }) - require.NoError(t, err) - - token, err := kubeClient.GetRefresh(r.ID) - require.NoError(t, err) - // Because concurrent update breaks the lock, the final result will be the value of the first update - require.Equal(t, "update-result-2", token.Token) - }) -} From 3dd4d2e85973af1a318f6c7b32a5060615a00944 Mon Sep 17 00:00:00 2001 From: Tommaso Sardelli Date: Wed, 19 Jul 2023 18:55:55 +0200 Subject: [PATCH 2/2] chore(actions): push images to datahow namespace, disable artifacts action and arm platforms --- .github/workflows/artifacts.yaml | 171 ++++++++++++------------- .github/workflows/codeql-analysis.yaml | 114 ++++++++--------- .github/workflows/docker.yaml | 20 +-- 3 files changed, 152 insertions(+), 153 deletions(-) diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml index 0237b3ac66..9abfdf7b43 100644 --- a/.github/workflows/artifacts.yaml +++ b/.github/workflows/artifacts.yaml @@ -1,97 +1,96 @@ -name: Artifacts +# name: Artifacts -on: - push: - branches: - - master - tags: - - v[0-9]+.[0-9]+.[0-9]+ - pull_request: +# on: +# push: +# branches: +# - master +# tags: +# - v[0-9]+.[0-9]+.[0-9]+ +# pull_request: -jobs: - container-images: - name: Container images - runs-on: ubuntu-latest - strategy: - matrix: - variant: - - alpine - - distroless +# jobs: +# container-images: +# name: Container images +# runs-on: ubuntu-latest +# strategy: +# matrix: +# variant: +# - alpine +# - distroless - steps: - - name: Checkout - uses: actions/checkout@v3 +# steps: +# - name: Checkout +# uses: actions/checkout@v3 - - name: Gather metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: | - ghcr.io/dexidp/dex - dexidp/dex - flavor: | - latest = false - tags: | - type=ref,event=branch,enable=${{ matrix.variant == 'alpine' }} - type=ref,event=pr,enable=${{ matrix.variant == 'alpine' }} - type=semver,pattern={{raw}},enable=${{ matrix.variant == 'alpine' }} - type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && matrix.variant == 'alpine' }} - type=ref,event=branch,suffix=-${{ matrix.variant }} - type=ref,event=pr,suffix=-${{ matrix.variant }} - type=semver,pattern={{raw}},suffix=-${{ matrix.variant }} - type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }},suffix=-${{ matrix.variant }} - labels: | - org.opencontainers.image.documentation=https://dexidp.io/docs/ +# - name: Gather metadata +# id: meta +# uses: docker/metadata-action@v4 +# with: +# images: | +# ghcr.io/datahow/dex +# flavor: | +# latest = false +# tags: | +# type=ref,event=branch,enable=${{ matrix.variant == 'alpine' }} +# type=ref,event=pr,enable=${{ matrix.variant == 'alpine' }} +# type=semver,pattern={{raw}},enable=${{ matrix.variant == 'alpine' }} +# type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && matrix.variant == 'alpine' }} +# type=ref,event=branch,suffix=-${{ matrix.variant }} +# type=ref,event=pr,suffix=-${{ matrix.variant }} +# type=semver,pattern={{raw}},suffix=-${{ matrix.variant }} +# type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }},suffix=-${{ matrix.variant }} +# labels: | +# org.opencontainers.image.documentation=https://dexidp.io/docs/ - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - with: - platforms: all +# - name: Set up QEMU +# uses: docker/setup-qemu-action@v2 +# with: +# platforms: all - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@v2 - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ github.token }} - if: github.event_name == 'push' +# - name: Login to GitHub Container Registry +# uses: docker/login-action@v2 +# with: +# registry: ghcr.io +# username: ${{ github.repository_owner }} +# password: ${{ github.token }} +# if: github.event_name == 'push' - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - if: github.event_name == 'push' +# # - name: Login to Docker Hub +# # uses: docker/login-action@v2 +# # with: +# # username: ${{ secrets.DOCKER_USERNAME }} +# # password: ${{ secrets.DOCKER_PASSWORD }} +# # if: github.event_name == 'push' - - name: Build and push - uses: docker/build-push-action@v3 - with: - context: . - platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le - # cache-from: type=gha - # cache-to: type=gha,mode=max - push: ${{ github.event_name == 'push' }} - tags: ${{ steps.meta.outputs.tags }} - build-args: | - BASE_IMAGE=${{ matrix.variant }} - VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} - COMMIT_HASH=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} - BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} - labels: ${{ steps.meta.outputs.labels }} +# - name: Build and push +# uses: docker/build-push-action@v3 +# with: +# context: . +# platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le +# # cache-from: type=gha +# # cache-to: type=gha,mode=max +# push: ${{ github.event_name == 'push' }} +# tags: ${{ steps.meta.outputs.tags }} +# build-args: | +# BASE_IMAGE=${{ matrix.variant }} +# VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} +# COMMIT_HASH=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} +# BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} +# labels: ${{ steps.meta.outputs.labels }} - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.7.1 - with: - image-ref: "ghcr.io/dexidp/dex:${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" - format: "sarif" - output: "trivy-results.sarif" - if: github.event_name == 'push' +# - name: Run Trivy vulnerability scanner +# uses: aquasecurity/trivy-action@0.7.1 +# with: +# image-ref: "ghcr.io/datahow/dex:${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" +# format: "sarif" +# output: "trivy-results.sarif" +# if: github.event_name == 'push' - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: "trivy-results.sarif" - if: github.event_name == 'push' +# - name: Upload Trivy scan results to GitHub Security tab +# uses: github/codeql-action/upload-sarif@v2 +# with: +# sarif_file: "trivy-results.sarif" +# if: github.event_name == 'push' diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 926f8be539..c7b37cecb5 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -1,67 +1,67 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" +# # For most projects, this workflow file will not need changing; you simply need +# # to commit it to your repository. +# # +# # You may wish to alter this file to override the set of languages analyzed, +# # or to provide custom queries or build logic. +# # +# # ******** NOTE ******** +# # We have attempted to detect the languages in your repository. Please check +# # the `language` matrix defined below to confirm you have the correct set of +# # supported CodeQL languages. +# # +# name: "CodeQL" -on: - push: - branches: [ master, v1 ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '28 10 * * 6' +# on: +# push: +# branches: [ master, v1 ] +# pull_request: +# # The branches below must be a subset of the branches above +# branches: [ master ] +# schedule: +# - cron: '28 10 * * 6' -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest +# jobs: +# analyze: +# name: Analyze +# runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - language: [ 'go' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed +# strategy: +# fail-fast: false +# matrix: +# language: [ 'go' ] +# # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] +# # Learn more: +# # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - steps: - - name: Checkout repository - uses: actions/checkout@v3 +# steps: +# - name: Checkout repository +# uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main +# # Initializes the CodeQL tools for scanning. +# - name: Initialize CodeQL +# uses: github/codeql-action/init@v2 +# with: +# languages: ${{ matrix.language }} +# # If you wish to specify custom queries, you can do so here or in a config file. +# # By default, queries listed here will override any specified in a config file. +# # Prefix the list here with "+" to use these queries and those in the config file. +# # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 +# # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). +# # If this step fails, then you should remove it and run the build manually (see below) +# - name: Autobuild +# uses: github/codeql-action/autobuild@v2 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl +# # ℹī¸ Command-line programs to run using the OS shell. +# # 📚 https://git.io/JvXDl - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language +# # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines +# # and modify them (or add more) to build your code if your project +# # uses a compiled language - #- run: | - # make bootstrap - # make release +# #- run: | +# # make bootstrap +# # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 +# - name: Perform CodeQL Analysis +# uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index f841d55640..21efbf5019 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -1,7 +1,7 @@ name: Docker on: - # push: + push: # branches: # - master # tags: @@ -20,7 +20,7 @@ jobs: - name: Calculate Docker image tags id: tags env: - DOCKER_IMAGES: "ghcr.io/dexidp/dex dexidp/dex" + DOCKER_IMAGES: "ghcr.io/datahow/dex" run: | case $GITHUB_REF in refs/tags/*) VERSION=${GITHUB_REF#refs/tags/};; @@ -64,18 +64,18 @@ jobs: password: ${{ github.token }} if: github.event_name == 'push' - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - if: github.event_name == 'push' + # - name: Login to Docker Hub + # uses: docker/login-action@v2 + # with: + # username: ${{ secrets.DOCKER_USERNAME }} + # password: ${{ secrets.DOCKER_PASSWORD }} + # if: github.event_name == 'push' - name: Build and push uses: docker/build-push-action@v3 with: context: . - platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le + platforms: linux/amd64 #,linux/arm/v7,linux/arm64,linux/ppc64le # cache-from: type=gha # cache-to: type=gha,mode=max push: ${{ github.event_name == 'push' }} @@ -98,7 +98,7 @@ jobs: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.7.1 with: - image-ref: "ghcr.io/dexidp/dex:${{ steps.tags.outputs.version }}" + image-ref: "ghcr.io/datahow/dex:${{ steps.tags.outputs.version }}" format: "template" template: "@/contrib/sarif.tpl" output: "trivy-results.sarif"