Skip to content

Commit

Permalink
fix(rbac): support RejectUnauthorized ssl option for postgres (#2122)
Browse files Browse the repository at this point in the history
* fix(rbac): added support for rejectUnauthorized in PG SSL options connection

* fix(rbac): make sure undefined properties are accepted

* fix(rbac): fix compilation and unit tests

Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>

* fix(rbac): refactor SSL handling to reuse existing types

Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>

---------

Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>
Co-authored-by: Boris Gershanik <boris@viber.com>
  • Loading branch information
AndrienkoAleksandr and Boris Gershanik authored Sep 9, 2024
1 parent 9202767 commit 4fe12a6
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 13 deletions.
1 change: 1 addition & 0 deletions plugins/rbac-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@backstage/errors": "^1.2.4",
"@backstage/plugin-auth-node": "^0.4.17",
"@backstage/plugin-permission-backend": "^0.5.46",
"@backstage/backend-defaults": "^0.4.1",
"@backstage/plugin-permission-common": "^0.8.0",
"@backstage/plugin-permission-node": "^0.8.0",
"@backstage/types": "^1.1.1",
Expand Down
70 changes: 70 additions & 0 deletions plugins/rbac-backend/src/database/casbin-adapter-factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,76 @@ describe('CasbinAdapterFactory', () => {
},
});
});

it('test building an adapter using a PostgreSQL configuration with intentionally ssl and TLS options.', async () => {
const config = new ConfigReader({
backend: {
database: {
client: 'pg',
connection: {
host: 'localhost',
port: '5432',
user: 'postgresUser',
password: process.env.TEST,
ssl: {
ca: 'abc',
rejectUnauthorized: false,
},
},
},
},
});
const factory = new CasbinDBAdapterFactory(config, db);
const adapter = await factory.createAdapter();
expect(adapter).not.toBeNull();
expect(newAdapterMock).toHaveBeenCalledWith({
type: 'postgres',
host: 'localhost',
port: 5432,
schema: 'public',
username: 'postgresUser',
password: process.env.TEST,
database: 'test-database',
ssl: {
ca: 'abc',
rejectUnauthorized: false,
},
});
});

it('test building an adapter using a PostgreSQL configuration with intentionally ssl without CA.', async () => {
const config = new ConfigReader({
backend: {
database: {
client: 'pg',
connection: {
host: 'localhost',
port: '5432',
user: 'postgresUser',
password: process.env.TEST,
ssl: {
rejectUnauthorized: false,
},
},
},
},
});
const factory = new CasbinDBAdapterFactory(config, db);
const adapter = await factory.createAdapter();
expect(adapter).not.toBeNull();
expect(newAdapterMock).toHaveBeenCalledWith({
type: 'postgres',
host: 'localhost',
port: 5432,
schema: 'public',
username: 'postgresUser',
password: process.env.TEST,
database: 'test-database',
ssl: {
rejectUnauthorized: false,
},
});
});
});

it('ensure that building an adapter with an unknown configuration fails.', async () => {
Expand Down
40 changes: 28 additions & 12 deletions plugins/rbac-backend/src/database/casbin-adapter-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { Knex } from 'knex';
import TypeORMAdapter from 'typeorm-adapter';

import { resolve } from 'path';
import { TlsOptions } from 'tls';
import { ConnectionOptions, TlsOptions } from 'tls';

import '@backstage/backend-defaults/database';

const DEFAULT_SQLITE3_STORAGE_FILE_NAME = 'rbac.sqlite';

Expand All @@ -26,7 +28,7 @@ export class CasbinDBAdapterFactory {
const schema =
(await this.databaseClient.client.searchPath?.[0]) ?? 'public';

const ssl = this.handleSSL(databaseConfig!);
const ssl = this.handlePostgresSSL(databaseConfig!);

adapter = await TypeORMAdapter.newAdapter({
type: 'postgres',
Expand Down Expand Up @@ -63,28 +65,42 @@ export class CasbinDBAdapterFactory {
return adapter;
}

private handleSSL(dbConfig: Config): boolean | TlsOptions | undefined {
const connection = dbConfig.getOptional('connection');
private handlePostgresSSL(
dbConfig: Config,
): boolean | TlsOptions | undefined {
const connection = dbConfig.getOptional<Knex.PgConnectionConfig | string>(
'connection',
);
if (!connection) {
return undefined;
}
const ssl = (connection as { ssl: Object | boolean | undefined }).ssl;

if (typeof connection === 'string' || connection instanceof String) {
throw new Error(
`rbac backend plugin doesn't support postgres connection in a string format yet`,
);
}

const ssl: boolean | ConnectionOptions | undefined = connection.ssl;

if (ssl === undefined) {
return undefined;
}

if (typeof ssl.valueOf() === 'boolean') {
if (typeof ssl === 'boolean') {
return ssl;
}

if (typeof ssl.valueOf() === 'object') {
const ca = (ssl as { ca: string }).ca;
if (ca) {
return { ca };
}
if (typeof ssl === 'object') {
const { ca, rejectUnauthorized } = ssl as ConnectionOptions;
const tlsOpts = { ca, rejectUnauthorized };

// SSL object was defined with some options that we don't support yet.
return true;
if (Object.values(tlsOpts).every(el => el === undefined)) {
return true;
}

return tlsOpts;
}

return undefined;
Expand Down
2 changes: 1 addition & 1 deletion plugins/rbac-backend/src/service/policy-builder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
createLegacyAuthAdapters,
DatabaseManager,
PluginEndpointDiscovery,
} from '@backstage/backend-common';
import { DatabaseManager } from '@backstage/backend-defaults/database';
import {
AuthService,
HttpAuthService,
Expand Down

0 comments on commit 4fe12a6

Please sign in to comment.