Example #1
0
        private AzureApp CreateApp(string loginEndPoint, HttpClient httpClient, string token, X509Certificate2 cert, string redirectUri)
        {
            var expirationDate = DateTime.Parse(cert.GetExpirationDateString()).ToUniversalTime();
            var startDate      = DateTime.Parse(cert.GetEffectiveDateString()).ToUniversalTime();

            var permissionScopes = new PermissionScopes();
            var scopes           = new List <PermissionScope>();

            if (this.Scopes != null)
            {
                foreach (var scopeIdentifier in this.Scopes)
                {
                    scopes.Add(permissionScopes.GetScope(scopeIdentifier));
                }
            }
            else
            {
                scopes.Add(permissionScopes.GetScope("SPO.Sites.FullControl.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.Group.ReadWrite.All"));
                scopes.Add(permissionScopes.GetScope("SPO.User.Read.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.User.Read.All"));
            }

            var scopesPayload = GetScopesPayload(scopes);
            var payload       = new
            {
                displayName    = ApplicationName,
                signInAudience = "AzureADMyOrg",
                keyCredentials = new[] {
                    new {
                        customKeyIdentifier = cert.GetCertHashString(),
                        endDateTime         = expirationDate,
                        keyId         = Guid.NewGuid().ToString(),
                        startDateTime = startDate,
                        type          = "AsymmetricX509Cert",
                        usage         = "Verify",
                        key           = Convert.ToBase64String(cert.GetRawCertData()),
                        displayName   = cert.Subject
                    }
                },
                publicClient = new
                {
                    redirectUris = new[] {
                        $"{loginEndPoint}/common/oauth2/nativeclient",
                        redirectUri
                    }
                },
                requiredResourceAccess = scopesPayload
            };
            var requestContent = new StringContent(JsonSerializer.Serialize(payload));

            requestContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

            var azureApp = GraphHelper.PostAsync <AzureApp>(httpClient, "/v1.0/applications", requestContent, token).GetAwaiter().GetResult();

            return(azureApp);
        }
        protected override void ProcessRecord()
        {
            var record = new PSObject();
            var token  = AzureAuthHelper.AuthenticateAsync(Tenant).GetAwaiter().GetResult();

            var cert = new X509Certificate2();

            if (ParameterSetName == ParameterSet_EXISTINGCERT)
            {
                if (ParameterSpecified(nameof(CertificatePassword)))
                {
                    cert.Import(CertificatePath, CertificatePassword, X509KeyStorageFlags.Exportable);
                }
                else
                {
                    cert.Import(CertificatePath);
                }
            }
            else
            {
                // Generate a certificate
                var x500Values = new List <string>();
                if (!MyInvocation.BoundParameters.ContainsKey("CommonName"))
                {
                    CommonName = ApplicationName;
                }
                if (!string.IsNullOrWhiteSpace(CommonName))
                {
                    x500Values.Add($"CN={CommonName}");
                }
                if (!string.IsNullOrWhiteSpace(Country))
                {
                    x500Values.Add($"C={Country}");
                }
                if (!string.IsNullOrWhiteSpace(State))
                {
                    x500Values.Add($"S={State}");
                }
                if (!string.IsNullOrWhiteSpace(Locality))
                {
                    x500Values.Add($"L={Locality}");
                }
                if (!string.IsNullOrWhiteSpace(Organization))
                {
                    x500Values.Add($"O={Organization}");
                }
                if (!string.IsNullOrWhiteSpace(OrganizationUnit))
                {
                    x500Values.Add($"OU={OrganizationUnit}");
                }

                string x500 = string.Join("; ", x500Values);

                if (ValidYears < 1 || ValidYears > 30)
                {
                    ValidYears = 10;
                }
                DateTime validFrom = DateTime.Today;
                DateTime validTo   = validFrom.AddYears(ValidYears);

                byte[] certificateBytes = CertificateHelper.CreateSelfSignCertificatePfx(x500, validFrom, validTo, CertificatePassword);
                cert = new X509Certificate2(certificateBytes, CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

                if (!string.IsNullOrWhiteSpace(OutPath))
                {
                    if (!Path.IsPathRooted(OutPath))
                    {
                        OutPath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, OutPath);
                    }
                    if (Directory.Exists(OutPath))
                    {
                        var    pfxPath     = Path.Combine(OutPath, $"{ApplicationName}.pfx");
                        byte[] certPfxData = cert.Export(X509ContentType.Pfx, CertificatePassword);
                        File.WriteAllBytes(pfxPath, certPfxData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Pfx file", pfxPath)));
                        var    cerPath     = Path.Combine(OutPath, $"{ApplicationName}.cer");
                        byte[] certCerData = cert.Export(X509ContentType.Cert);
                        File.WriteAllBytes(cerPath, certCerData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Cer file", cerPath)));
                    }
                }
                if (ParameterSpecified(nameof(Store)))
                {
                    using (var store = new X509Store("My", Store))
                    {
                        store.Open(OpenFlags.ReadWrite);
                        store.Add(cert);
                        store.Close();
                    }
                    Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "Certificate added to store");
                }
            }

            var expirationDate = DateTime.Parse(cert.GetExpirationDateString()).ToUniversalTime();
            var startDate      = DateTime.Parse(cert.GetEffectiveDateString()).ToUniversalTime();

            if (token != null)
            {
                var permissionScopes = new PermissionScopes();
                var scopes           = new List <PermissionScope>();
                if (this.Scopes != null)
                {
                    foreach (var scopeIdentifier in this.Scopes)
                    {
                        scopes.Add(permissionScopes.GetScope(scopeIdentifier));
                    }
                }
                else
                {
                    scopes.Add(permissionScopes.GetScope("SPO.Sites.FullControl.All"));
                    scopes.Add(permissionScopes.GetScope("MSGraph.Group.ReadWrite.All"));
                    scopes.Add(permissionScopes.GetScope("SPO.User.Read.All"));
                    scopes.Add(permissionScopes.GetScope("MSGraph.User.Read.All"));
                }

                var scopesPayload = GetScopesPayload(scopes);
                var payload       = new
                {
                    displayName    = ApplicationName,
                    signInAudience = "AzureADMyOrg",
                    keyCredentials = new[] {
                        new {
                            customKeyIdentifier = cert.GetCertHashString(),
                            endDateTime         = expirationDate,
                            keyId         = Guid.NewGuid().ToString(),
                            startDateTime = startDate,
                            type          = "AsymmetricX509Cert",
                            usage         = "Verify",
                            key           = Convert.ToBase64String(cert.GetRawCertData())
                        }
                    },
                    publicClient = new
                    {
                        redirectUris = new[] {
                            "https://login.microsoftonline.com/common/oauth2/nativeclient",
                        }
                    },
                    requiredResourceAccess = scopesPayload
                };
                var postResult = HttpHelper.MakePostRequestForString("https://graph.microsoft.com/beta/applications", payload, "application/json", token);
                var azureApp   = JsonConvert.DeserializeObject <AzureApp>(postResult);
                record.Properties.Add(new PSVariableProperty(new PSVariable("AzureAppId", azureApp.AppId)));

                var waitTime = 60;
                Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"Waiting {waitTime} seconds to launch consent flow in a browser window. This wait is required to make sure that Azure AD is able to initialize all required artifacts.");
                for (var i = 0; i < waitTime; i++)
                {
                    Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, ".");
                    System.Threading.Thread.Sleep(1000);
                }
                Host.UI.WriteLine();
                var consentUrl = $"https://login.microsoftonline.com/{Tenant}/v2.0/adminconsent?client_id={azureApp.AppId}&scope=https://microsoft.sharepoint-df.com/.default";
                record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate Thumbprint", cert.GetCertHashString())));

                AzureAuthHelper.OpenConsentFlow(consentUrl, (message) =>
                {
                    Host.UI.WriteLine(ConsoleColor.Red, Host.UI.RawUI.BackgroundColor, message);
                });
                WriteObject(record);
            }
        }
        protected override void ProcessRecord()
        {
            var loginEndPoint = string.Empty;
            var record        = new PSObject();

            using (var authenticationManager = new AuthenticationManager())
            {
                loginEndPoint = authenticationManager.GetAzureADLoginEndPoint(AzureEnvironment);
            }
            if (!ParameterSpecified(nameof(Password)))
            {
                Host.UI.Write("Password: "******"The specified network password is not correct"))
                    {
                        throw new PSArgumentNullException(nameof(CertificatePassword), string.Format(Resources.PrivateKeyCertificateImportFailedPasswordIncorrect, nameof(CertificatePassword)));
                    }
                }
                else
                {
                    try
                    {
                        cert.Import(CertificatePath);
                    }
                    catch (CryptographicException e) when(e.Message.Contains("The specified network password is not correct"))
                    {
                        throw new PSArgumentNullException(nameof(CertificatePassword), string.Format(Resources.PrivateKeyCertificateImportFailedPasswordMissing, nameof(CertificatePassword)));
                    }
                }

                // Ensure the certificate at the provided CertificatePath holds a private key
                if (!cert.HasPrivateKey)
                {
                    throw new PSArgumentException(string.Format(Resources.CertificateAtPathHasNoPrivateKey, CertificatePath), nameof(CertificatePath));
                }
            }
            else
            {
                // Generate a certificate
                var x500Values = new List <string>();
                if (!MyInvocation.BoundParameters.ContainsKey("CommonName"))
                {
                    CommonName = ApplicationName;
                }
                if (!string.IsNullOrWhiteSpace(CommonName))
                {
                    x500Values.Add($"CN={CommonName}");
                }
                if (!string.IsNullOrWhiteSpace(Country))
                {
                    x500Values.Add($"C={Country}");
                }
                if (!string.IsNullOrWhiteSpace(State))
                {
                    x500Values.Add($"S={State}");
                }
                if (!string.IsNullOrWhiteSpace(Locality))
                {
                    x500Values.Add($"L={Locality}");
                }
                if (!string.IsNullOrWhiteSpace(Organization))
                {
                    x500Values.Add($"O={Organization}");
                }
                if (!string.IsNullOrWhiteSpace(OrganizationUnit))
                {
                    x500Values.Add($"OU={OrganizationUnit}");
                }

                string x500 = string.Join("; ", x500Values);

                if (ValidYears < 1 || ValidYears > 30)
                {
                    ValidYears = 10;
                }
                DateTime validFrom = DateTime.Today;
                DateTime validTo   = validFrom.AddYears(ValidYears);

                byte[] certificateBytes = CertificateHelper.CreateSelfSignCertificatePfx(x500, validFrom, validTo, CertificatePassword);
                cert = new X509Certificate2(certificateBytes, CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

                if (!string.IsNullOrWhiteSpace(OutPath))
                {
                    if (!Path.IsPathRooted(OutPath))
                    {
                        OutPath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, OutPath);
                    }
                    if (Directory.Exists(OutPath))
                    {
                        var    pfxPath     = Path.Combine(OutPath, $"{ApplicationName}.pfx");
                        byte[] certPfxData = cert.Export(X509ContentType.Pfx, CertificatePassword);
                        File.WriteAllBytes(pfxPath, certPfxData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Pfx file", pfxPath)));
                        var    cerPath     = Path.Combine(OutPath, $"{ApplicationName}.cer");
                        byte[] certCerData = cert.Export(X509ContentType.Cert);
                        File.WriteAllBytes(cerPath, certCerData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Cer file", cerPath)));
                    }
                }
                if (ParameterSpecified(nameof(Store)))
                {
                    using (var store = new X509Store("My", Store))
                    {
                        store.Open(OpenFlags.ReadWrite);
                        store.Add(cert);
                        store.Close();
                    }
                    Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "Certificate added to store");
                }
            }

            var expirationDate = DateTime.Parse(cert.GetExpirationDateString()).ToUniversalTime();
            var startDate      = DateTime.Parse(cert.GetEffectiveDateString()).ToUniversalTime();

            if (token != null)
            {
                var permissionScopes = new PermissionScopes();
                var scopes           = new List <PermissionScope>();
                if (this.Scopes != null)
                {
                    foreach (var scopeIdentifier in this.Scopes)
                    {
                        scopes.Add(permissionScopes.GetScope(scopeIdentifier));
                    }
                }
                else
                {
                    scopes.Add(permissionScopes.GetScope("SPO.Sites.FullControl.All"));
                    scopes.Add(permissionScopes.GetScope("MSGraph.Group.ReadWrite.All"));
                    scopes.Add(permissionScopes.GetScope("SPO.User.Read.All"));
                    scopes.Add(permissionScopes.GetScope("MSGraph.User.Read.All"));
                }

                var scopesPayload = GetScopesPayload(scopes);
                var payload       = new
                {
                    displayName    = ApplicationName,
                    signInAudience = "AzureADMyOrg",
                    keyCredentials = new[] {
                        new {
                            customKeyIdentifier = cert.GetCertHashString(),
                            endDateTime         = expirationDate,
                            keyId         = Guid.NewGuid().ToString(),
                            startDateTime = startDate,
                            type          = "AsymmetricX509Cert",
                            usage         = "Verify",
                            key           = Convert.ToBase64String(cert.GetRawCertData())
                        }
                    },
                    publicClient = new
                    {
                        redirectUris = new[] {
                            $"{loginEndPoint}/common/oauth2/nativeclient"
                        }
                    },
                    requiredResourceAccess = scopesPayload
                };
                var requestContent = new StringContent(JsonSerializer.Serialize(payload));
                requestContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                var azureApp = GraphHelper.PostAsync <AzureApp>(new System.Net.Http.HttpClient(), "/beta/applications", requestContent, token).GetAwaiter().GetResult();
                record.Properties.Add(new PSVariableProperty(new PSVariable("AzureAppId", azureApp.AppId)));

                var consentUrl = $"{loginEndPoint}/{Tenant}/v2.0/adminconsent?client_id={azureApp.AppId}&scope=https://microsoft.sharepoint-df.com/.default";
                record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate Thumbprint", cert.GetCertHashString())));


                var waitTime = 60;
                Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"Waiting {waitTime} seconds to launch consent flow in a browser window. This wait is required to make sure that Azure AD is able to initialize all required artifacts. After you provided consent you will see a blank page. This is expected. You can always navigate to the consent page manually: {consentUrl}");

                Console.TreatControlCAsInput = true;

                for (var i = 0; i < waitTime; i++)
                {
                    Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, ".");
                    System.Threading.Thread.Sleep(1000);

                    // Check if CTRL+C has been pressed and if so, abort the wait
                    if (Host.UI.RawUI.KeyAvailable)
                    {
                        var key = Host.UI.RawUI.ReadKey(ReadKeyOptions.AllowCtrlC | ReadKeyOptions.NoEcho | ReadKeyOptions.IncludeKeyUp);
                        if ((key.ControlKeyState.HasFlag(ControlKeyStates.LeftCtrlPressed) || key.ControlKeyState.HasFlag(ControlKeyStates.RightCtrlPressed)) && key.VirtualKeyCode == 67)
                        {
                            break;
                        }
                    }
                }
                Host.UI.WriteLine();


                WriteObject(record);

                BrowserHelper.LaunchBrowser(consentUrl);

                //AzureAuthHelper.OpenConsentFlow(consentUrl, (message) =>
                //{
                //    Host.UI.WriteLine(ConsoleColor.Red, Host.UI.RawUI.BackgroundColor, message);
                //});
            }
        }
        protected override void ProcessRecord()
        {
            if (ParameterSpecified(nameof(Store)) && !OperatingSystem.IsWindows())
            {
                throw new PSArgumentException("The Store parameter is only supported on Microsoft Windows");
            }

            if (!string.IsNullOrWhiteSpace(OutPath))
            {
                if (!Path.IsPathRooted(OutPath))
                {
                    OutPath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, OutPath);
                }
            }
            else
            {
                OutPath = SessionState.Path.CurrentFileSystemLocation.Path;
            }

            var redirectUri = "http://localhost";

            if (ParameterSpecified(nameof(DeviceLogin)))
            {
                redirectUri = "https://pnp.github.io/powershell/consent.html";
            }

            var messageWriter = new CmdletMessageWriter(this);

            cancellationTokenSource = new CancellationTokenSource();
            CancellationToken cancellationToken = cancellationTokenSource.Token;

            var loginEndPoint = string.Empty;

            using (var authenticationManager = new AuthenticationManager())
            {
                loginEndPoint = authenticationManager.GetAzureADLoginEndPoint(AzureEnvironment);
            }

            var permissionScopes = new PermissionScopes();
            var scopes           = new List <PermissionScope>();

            if (this.Scopes != null)
            {
                foreach (var scopeIdentifier in this.Scopes)
                {
                    scopes.Add(permissionScopes.GetScope(scopeIdentifier));
                }
            }
            else
            {
                scopes.Add(permissionScopes.GetScope("SPO.Sites.FullControl.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.Group.ReadWrite.All"));
                scopes.Add(permissionScopes.GetScope("SPO.User.Read.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.User.Read.All"));
            }

            var record = new PSObject();

            string token = GetAuthToken(messageWriter);

            if (!string.IsNullOrEmpty(token))
            {
                var cert = GetCertificate(record);

                using (var httpClient = new HttpClient())
                {
                    if (!AppExists(ApplicationName, httpClient, token))
                    {
                        var azureApp = CreateApp(loginEndPoint, httpClient, token, cert, redirectUri, scopes);

                        record.Properties.Add(new PSVariableProperty(new PSVariable("AzureAppId/ClientId", azureApp.AppId)));
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate Thumbprint", cert.GetCertHashString())));
                        byte[] certPfxData  = cert.Export(X509ContentType.Pfx, CertificatePassword);
                        var    base64String = Convert.ToBase64String(certPfxData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Base64Encoded", base64String)));
                        StartConsentFlow(loginEndPoint, azureApp, redirectUri, token, httpClient, record, messageWriter, scopes);
                    }
                    else
                    {
                        throw new PSInvalidOperationException($"The application with name {ApplicationName} already exists.");
                    }
                }
            }
        }