-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[oidc] Setup db #15305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[oidc] Setup db #15305
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) 2022 Gitpod GmbH. All rights reserved. | ||
// Licensed under the GNU Affero General Public License (AGPL). | ||
// See License.AGPL.txt in the project root for license information. | ||
|
||
package dbtest | ||
|
||
import ( | ||
"context" | ||
db "github.com/gitpod-io/gitpod/components/gitpod-db/go" | ||
"github.com/google/uuid" | ||
"github.com/stretchr/testify/require" | ||
"gorm.io/gorm" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func NewOIDCClientConfig(t *testing.T, record db.OIDCClientConfig) db.OIDCClientConfig { | ||
t.Helper() | ||
|
||
now := time.Now().UTC().Truncate(time.Millisecond) | ||
result := db.OIDCClientConfig{ | ||
ID: uuid.New(), | ||
Issuer: "issuer", | ||
Data: []byte("{}"), | ||
LastModified: now, | ||
} | ||
|
||
if record.ID != uuid.Nil { | ||
result.ID = record.ID | ||
} | ||
|
||
if record.Issuer != "" { | ||
result.Issuer = record.Issuer | ||
} | ||
|
||
if record.Data != nil { | ||
result.Data = record.Data | ||
} | ||
|
||
return result | ||
} | ||
|
||
func CreateOIDCClientConfigs(t *testing.T, conn *gorm.DB, entries ...db.OIDCClientConfig) []db.OIDCClientConfig { | ||
t.Helper() | ||
|
||
var records []db.OIDCClientConfig | ||
var ids []string | ||
for _, entry := range entries { | ||
record := NewOIDCClientConfig(t, entry) | ||
records = append(records, record) | ||
ids = append(ids, record.ID.String()) | ||
|
||
_, err := db.CreateOIDCCLientConfig(context.Background(), conn, record) | ||
require.NoError(t, err) | ||
} | ||
|
||
t.Cleanup(func() { | ||
if len(ids) > 0 { | ||
require.NoError(t, conn.Where(ids).Delete(&db.OIDCClientConfig{}).Error) | ||
} | ||
}) | ||
|
||
return records | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright (c) 2022 Gitpod GmbH. All rights reserved. | ||
// Licensed under the GNU Affero General Public License (AGPL). | ||
// See License.AGPL.txt in the project root for license information. | ||
|
||
package db | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"github.com/google/uuid" | ||
"gorm.io/datatypes" | ||
"gorm.io/gorm" | ||
"time" | ||
) | ||
|
||
type OIDCClientConfig struct { | ||
ID uuid.UUID `gorm:"primary_key;column:id;type:char;size:36;" json:"id"` | ||
|
||
Issuer string `gorm:"column:issuer;type:char;size:255;" json:"issuer"` | ||
|
||
Data datatypes.JSON `gorm:"column:data;type:text;size:65535" json:"data"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the idea to store common properties such as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issuer is the domain, as per the oidc spec There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, for now we're storing them as json |
||
|
||
LastModified time.Time `gorm:"column:_lastModified;type:timestamp;default:CURRENT_TIMESTAMP(6);" json:"_lastModified"` | ||
// deleted is reserved for use by db-sync. | ||
_ bool `gorm:"column:deleted;type:tinyint;default:0;" json:"deleted"` | ||
} | ||
|
||
func (c *OIDCClientConfig) TableName() string { | ||
return "d_b_oidc_client_config" | ||
} | ||
|
||
func CreateOIDCCLientConfig(ctx context.Context, conn *gorm.DB, cfg OIDCClientConfig) (OIDCClientConfig, error) { | ||
if cfg.ID == uuid.Nil { | ||
return OIDCClientConfig{}, errors.New("OIDC Client Config ID must be set") | ||
} | ||
|
||
if cfg.Issuer == "" { | ||
return OIDCClientConfig{}, errors.New("OIDC Client Config issuer must be set") | ||
} | ||
|
||
tx := conn. | ||
WithContext(ctx). | ||
Create(&cfg) | ||
if tx.Error != nil { | ||
return OIDCClientConfig{}, fmt.Errorf("failed to create oidc client config: %w", tx.Error) | ||
} | ||
|
||
return cfg, nil | ||
} | ||
|
||
func GetOIDCClientConfig(ctx context.Context, conn *gorm.DB, id uuid.UUID) (OIDCClientConfig, error) { | ||
var config OIDCClientConfig | ||
|
||
if id == uuid.Nil { | ||
return OIDCClientConfig{}, fmt.Errorf("OIDC Client Config ID is a required argument") | ||
} | ||
|
||
tx := conn. | ||
WithContext(ctx). | ||
Where("id = ?", id). | ||
Where("deleted = ?", 0). | ||
First(&config) | ||
if tx.Error != nil { | ||
if errors.Is(tx.Error, gorm.ErrRecordNotFound) { | ||
return OIDCClientConfig{}, fmt.Errorf("OIDC Client Config with ID %s does not exist: %w", id, ErrorNotFound) | ||
} | ||
return OIDCClientConfig{}, fmt.Errorf("Failed to retrieve OIDC client config: %v", tx.Error) | ||
} | ||
|
||
return config, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright (c) 2022 Gitpod GmbH. All rights reserved. | ||
// Licensed under the GNU Affero General Public License (AGPL). | ||
// See License.AGPL.txt in the project root for license information. | ||
|
||
package db_test | ||
|
||
import ( | ||
"context" | ||
db "github.com/gitpod-io/gitpod/components/gitpod-db/go" | ||
"github.com/gitpod-io/gitpod/components/gitpod-db/go/dbtest" | ||
"github.com/stretchr/testify/require" | ||
"testing" | ||
) | ||
|
||
func TestCreateOIDCClientConfig_Create(t *testing.T) { | ||
conn := dbtest.ConnectForTests(t) | ||
created := dbtest.CreateOIDCClientConfigs(t, conn, db.OIDCClientConfig{})[0] | ||
|
||
retrieved, err := db.GetOIDCClientConfig(context.Background(), conn, created.ID) | ||
require.NoError(t, err) | ||
require.Equal(t, created, retrieved) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* Copyright (c) 2022 Gitpod GmbH. All rights reserved. | ||
* Licensed under the GNU Affero General Public License (AGPL). | ||
* See License.AGPL.txt in the project root for license information. | ||
*/ | ||
|
||
import { MigrationInterface, QueryRunner } from "typeorm"; | ||
import { tableExists } from "./helper/helper"; | ||
|
||
export class CreateOIDCClientConfigTable1670850042413 implements MigrationInterface { | ||
public async up(queryRunner: QueryRunner): Promise<void> { | ||
if (!(await tableExists(queryRunner, "d_b_oidc_client_config"))) { | ||
await queryRunner.query( | ||
"CREATE TABLE IF NOT EXISTS `d_b_oidc_client_config` (`id` varchar(255) NOT NULL, `issuer` varchar(255) NOT NULL, `data` text(65535) NOT NULL, `_lastModified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `deleted` tinyint(4) NOT NULL DEFAULT '0', PRIMARY KEY (id))", | ||
); | ||
} | ||
} | ||
|
||
public async down(queryRunner: QueryRunner): Promise<void> { | ||
if (await tableExists(queryRunner, "d_b_oidc_client_config")) { | ||
await queryRunner.query("DROP TABLE `d_b_oidc_client_config`"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the issuer referring to? a user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the issuer as per the OIDC spec. It can be google for @google.com domains, but other one also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Issuer (URL) is the ID of a IdP. That's also what is used to associate and validate the ID-tokens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it Issuer or Issuer Identifier?
From the spec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the
Issuer Identifier
indeed. But it's shortened to simpleIssuer
(or eveniss
when talking about claims) in the details of implementation.So, the issuer is actually an entity, but on the API level we're naming the URL as such.