Skip to content
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

cli doctor: show scopes by resource #5520

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 50 additions & 13 deletions src/m365/cli/commands/cli-doctor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ describe(commands.DOCTOR, () => {

it('retrieves scopes in the diagnostic information about the current environment', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
scp: 'AllSites.FullControl AppCatalog.ReadWrite.All'
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -98,18 +99,25 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: ['AllSites.FullControl', 'AppCatalog.ReadWrite.All']
scopes: {
'https://graph.microsoft.com': [
'AllSites.FullControl',
'AppCatalog.ReadWrite.All'
]
}
}));
});

it('retrieves scopes from multiple access tokens in the diagnostic information about the current environment', async () => {
const jwt1 = JSON.stringify({
aud: 'https://graph.microsoft.com',
scp: 'AllSites.FullControl AppCatalog.ReadWrite.All'
});
let jwt64 = Buffer.from(jwt1).toString('base64');
const accessToken1 = `abc.${jwt64}.def`;

const jwt2 = JSON.stringify({
aud: 'https://mydev.sharepoint.com',
scp: 'TermStore.Read.All'
});
jwt64 = Buffer.from(jwt2).toString('base64');
Expand Down Expand Up @@ -140,12 +148,21 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: ['AllSites.FullControl', 'AppCatalog.ReadWrite.All', 'TermStore.Read.All']
scopes: {
'https://graph.microsoft.com': [
'AllSites.FullControl',
'AppCatalog.ReadWrite.All'
],
'https://mydev.sharepoint.com': [
'TermStore.Read.All'
]
}
}));
});

it('retrieves roles in the diagnostic information about the current environment', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -175,18 +192,20 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: []
scopes: {}
}));
});

it('retrieves roles from multiple access tokens in the diagnostic information about the current environment', async () => {
const jwt1 = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
let jwt64 = Buffer.from(jwt1).toString('base64');
const accessToken1 = `abc.${jwt64}.def`;

const jwt2 = JSON.stringify({
aud: 'https://mydev.sharepoint.com',
roles: ['TermStore.Read.All']
});
jwt64 = Buffer.from(jwt2).toString('base64');
Expand Down Expand Up @@ -217,12 +236,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All', 'TermStore.Read.All'],
scopes: []
scopes: {}
}));
});

it('retrieves roles and scopes in the diagnostic information about the current environment', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scp: 'Sites.Read.All Files.ReadWrite.All'
});
Expand Down Expand Up @@ -253,12 +273,19 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: ['Sites.Read.All', 'Files.ReadWrite.All']
scopes: {
'https://graph.microsoft.com':
[
'Sites.Read.All',
'Files.ReadWrite.All'
]
}
}));
});

it('retrieves diagnostic information about the current environment when there are no roles or scopes available', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: [],
scp: ''
});
Expand Down Expand Up @@ -290,12 +317,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: []
scopes: {}
}));
});

it('retrieves diagnostic information about the current environment with auth type Certificate', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -325,12 +353,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: []
scopes: {}
}));
});

it('retrieves tenant information as single when TenantID is a GUID', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -360,12 +389,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: []
scopes: {}
}));
});

it('retrieves diagnostic information about the current environment (debug)', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -395,12 +425,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: []
scopes: {}
}));
});

it('retrieves diagnostic information of the current environment when executing in docker', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
roles: ['Sites.Read.All', 'Files.ReadWrite.All']
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -430,7 +461,7 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: ['Sites.Read.All', 'Files.ReadWrite.All'],
scopes: []
scopes: {}
}));
});

Expand Down Expand Up @@ -459,7 +490,7 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: []
scopes: {}
}));
});

Expand Down Expand Up @@ -489,12 +520,13 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: []
scopes: {}
}));
});

it('retrieves CLI Configuration in the diagnostic information about the current environment', async () => {
const jwt = JSON.stringify({
aud: 'https://graph.microsoft.com',
scp: 'AllSites.FullControl AppCatalog.ReadWrite.All'
});
const jwt64 = Buffer.from(jwt).toString('base64');
Expand Down Expand Up @@ -528,7 +560,12 @@ describe(commands.DOCTOR, () => {
nodeVersion: 'v14.17.0',
os: { 'platform': 'win32', 'version': 'Windows 10 Pro', 'release': '10.0.19043' },
roles: [],
scopes: ['AllSites.FullControl', 'AppCatalog.ReadWrite.All']
scopes: {
'https://graph.microsoft.com': [
'AllSites.FullControl',
'AppCatalog.ReadWrite.All'
]
}
}));
});
});
23 changes: 14 additions & 9 deletions src/m365/cli/commands/cli-doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface CliDiagnosticInfo {
cliVersion: string;
cliConfig: any;
roles: string[];
scopes: string[];
scopes: object
martinlingstuyl marked this conversation as resolved.
Show resolved Hide resolved
}

class CliDoctorCommand extends Command {
Expand All @@ -35,13 +35,16 @@ class CliDoctorCommand extends Command {

public async commandAction(logger: Logger): Promise<void> {
const roles: string[] = [];
const scopes: string[] = [];
const scopes: Map<string, string[]> = new Map<string, string[]>();

Object.keys(auth.service.accessTokens).forEach(resource => {
const accessToken: string = auth.service.accessTokens[resource].accessToken;

this.getRolesFromAccessToken(accessToken).forEach(role => roles.push(role));
this.getScopesFromAccessToken(accessToken).forEach(scope => scopes.push(scope));
const [res, scp] = this.getScopesFromAccessToken(accessToken);
martinlingstuyl marked this conversation as resolved.
Show resolved Hide resolved
if (res !== "") {
scopes.set(res, scp);
}
});

const diagnosticInfo: CliDiagnosticInfo = {
Expand All @@ -58,7 +61,7 @@ class CliDoctorCommand extends Command {
cliEnvironment: process.env.CLIMICROSOFT365_ENV ? process.env.CLIMICROSOFT365_ENV : '',
cliConfig: Cli.getInstance().config.all,
roles: roles,
scopes: scopes
scopes: Object.fromEntries(scopes)
};

await logger.log(diagnosticInfo);
Expand All @@ -85,26 +88,28 @@ class CliDoctorCommand extends Command {
return roles;
}

private getScopesFromAccessToken(accessToken: string): string[] {
private getScopesFromAccessToken(accessToken: string): [string, string[]] {
let resource: string = "";
let scopes: string[] = [];

if (!accessToken || accessToken.length === 0) {
return scopes;
return [resource, scopes];
}

const chunks = accessToken.split('.');
if (chunks.length !== 3) {
return scopes;
return [resource, scopes];
}

const tokenString: string = Buffer.from(chunks[1], 'base64').toString();

const token: { scp: string } = JSON.parse(tokenString);
const token: { aud: string, scp: string } = JSON.parse(tokenString);
if (token.scp?.length > 0) {
resource = token.aud;
scopes = token.scp.split(' ');
}

return scopes;
return [resource, scopes];
}
}

Expand Down