diff --git a/appengine/flexible/SocialAuth/Add-KmsPermissions.ps1 b/appengine/flexible/SocialAuth/Add-KmsPermissions.ps1
new file mode 100644
index 0000000000..b3cfd3b8f1
--- /dev/null
+++ b/appengine/flexible/SocialAuth/Add-KmsPermissions.ps1
@@ -0,0 +1,81 @@
+# Copyright (c) 2018 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+##############################
+#.SYNOPSIS
+# Updates permissions for KMS so that the service account can create KMS keys
+# and encrypt and decrypt data.
+#
+#.PARAMETER ServiceAccountEmail
+# The email address of the service account.
+#
+#.PARAMETER ProjectId
+# The Google Cloud Project ID to add permissions to.
+#
+#.EXAMPLE
+# .\Add-KmsPermissions.ps1. my-service-account@my-project.iam.gserviceaccount.com
+##############################
+
+Param (
+ [Parameter(Mandatory=$true)][string]$ServiceAccountEmail,
+ [string]$ProjectId
+)
+
+gcloud services enable cloudkms.googleapis.com
+
+$email = if (-not $ServiceAccountEmail.Contains('@')) {
+ (gcloud iam service-accounts list --format=json "--filter=email:($ServiceAccountEmail@*)" `
+ | ConvertFrom-Json).email
+} else {
+ $ServiceAccountEmail
+}
+
+$projectId = if ($ProjectId) {
+ $ProjectId
+} else {
+ gcloud config get-value project
+}
+
+###############################################################################
+# Permissions for App Engine to decrypt appsecrets.json.
+$keyName = [string] (Get-Content ./appsecrets.json.keyname)
+# Drop the last two segments of the path to get the key ring name.
+$keyRingName = ($keyName.Split('/') | Select-Object -SkipLast 2) -join "/"
+# Give App Engine permission to decrypt using keys in this keyring.
+$role = 'roles/cloudkms.cryptoKeyDecrypter'
+Write-Host "Adding role $role to $email for $keyRingName."
+gcloud kms keyrings add-iam-policy-binding $keyRingName `
+ --member serviceAccount:$email --role $role
+
+###############################################################################
+# Permissions for App Engine to encrypt and decrypt secrets for
+# KmsDataProtectionProvider.
+
+# Check to see if the key ring already exists.
+$keyRingId = 'dataprotectionprovider'
+# Check to see if the key ring already exists.
+$matchingKeyRing = (gcloud kms keyrings list --format json --location global --filter="name~.*/$keyRingId" | convertfrom-json).name
+if (-not $matchingKeyRing) {
+ # Create the new key ring.
+ Write-Host "Creating new key ring $keyRingId..."
+ gcloud kms keyrings create $keyRingId --location global
+}
+
+$roles = @('roles/cloudkms.admin', 'roles/cloudkms.cryptoKeyEncrypterDecrypter')
+foreach ($role in $roles) {
+ Write-Host "Adding role $role to $email for $keyRingId."
+ gcloud kms keyrings add-iam-policy-binding $keyRingId `
+ --project $projectId --location 'global' `
+ --member serviceAccount:$email --role $role
+}
diff --git a/appengine/flexible/SocialAuth/Add-KmsPermissionsToAppEngine.ps1 b/appengine/flexible/SocialAuth/Add-KmsPermissionsToAppEngine.ps1
index 5e5c10ffa2..8b2ffb7891 100644
--- a/appengine/flexible/SocialAuth/Add-KmsPermissionsToAppEngine.ps1
+++ b/appengine/flexible/SocialAuth/Add-KmsPermissionsToAppEngine.ps1
@@ -24,8 +24,6 @@
#.EXAMPLE
# .\Add-KmsPermissionsToAppEngine.ps1.
##############################
-gcloud services enable cloudkms.googleapis.com
-
# Look up the app engine account email address and project name.
$accounts = gcloud iam service-accounts list --format=json | ConvertFrom-Json
@@ -39,35 +37,4 @@ if (-not $appEngineAccount) {
$email = $appEngineAccount.email
$projectId = $appEngineAccount.projectId
-###############################################################################
-# Permissions for App Engine to decrypt appsecrets.json.
-$keyName = [string] (Get-Content ./appsecrets.json.keyname)
-# Drop the last two segments of the path to get the key ring name.
-$keyRingName = ($keyName.Split('/') | Select-Object -SkipLast 2) -join "/"
-# Give App Engine permission to decrypt using keys in this keyring.
-$role = 'roles/cloudkms.cryptoKeyDecrypter'
-Write-Host "Adding role $role to $email for $keyRingName."
-gcloud kms keyrings add-iam-policy-binding $keyRingName `
- --member serviceAccount:$email --role $role
-
-###############################################################################
-# Permissions for App Engine to encrypt and decrypt secrets for
-# KmsDataProtectionProvider.
-
-# Check to see if the key ring already exists.
-$keyRingId = 'dataprotectionprovider'
-# Check to see if the key ring already exists.
-$matchingKeyRing = (gcloud kms keyrings list --format json --location global --filter="name~.*/$keyRingId" | convertfrom-json).name
-if (-not $matchingKeyRing) {
- # Create the new key ring.
- Write-Host "Creating new key ring $keyRingId..."
- gcloud kms keyrings create $keyRingId --location global
-}
-
-$roles = @('roles/cloudkms.admin', 'roles/cloudkms.cryptoKeyEncrypterDecrypter')
-foreach ($role in $roles) {
- Write-Host "Adding role $role to $email for $keyRingId."
- gcloud kms keyrings add-iam-policy-binding $keyRingId `
- --project $projectId --location 'global' `
- --member serviceAccount:$email --role $role
-}
+.\Add-KmsPermissions.ps1 $email $projectId
\ No newline at end of file
diff --git a/appengine/flexible/SocialAuth/Dockerfile b/appengine/flexible/SocialAuth/Dockerfile
new file mode 100644
index 0000000000..7ad82be6a3
--- /dev/null
+++ b/appengine/flexible/SocialAuth/Dockerfile
@@ -0,0 +1,5 @@
+FROM gcr.io/google-appengine/aspnetcore:2.1
+COPY . /app
+ENV ASPNETCORE_URLS=http://*:${PORT}
+WORKDIR /app
+ENTRYPOINT ["dotnet", "SocialAuth.dll"]
diff --git a/appengine/flexible/SocialAuth/Services/KmsDataProtectionProvider.cs b/appengine/flexible/SocialAuth/Services/KmsDataProtectionProvider.cs
index 19b2a927e0..910a02c65b 100644
--- a/appengine/flexible/SocialAuth/Services/KmsDataProtectionProvider.cs
+++ b/appengine/flexible/SocialAuth/Services/KmsDataProtectionProvider.cs
@@ -72,6 +72,11 @@ public class KmsDataProtectionProvider : IDataProtectionProvider
{
// Already exists. Ok.
}
+ catch (Grpc.Core.RpcException e)
+ when (e.StatusCode == StatusCode.PermissionDenied)
+ {
+ // We don't need to create it as long as it exists.
+ }
}
IDataProtector IDataProtectionProvider.CreateProtector(string purpose)
diff --git a/appengine/flexible/SocialAuth/SocialAuth.csproj b/appengine/flexible/SocialAuth/SocialAuth.csproj
index 0ff8167440..06e128f52b 100644
--- a/appengine/flexible/SocialAuth/SocialAuth.csproj
+++ b/appengine/flexible/SocialAuth/SocialAuth.csproj
@@ -16,6 +16,7 @@
+
diff --git a/appengine/flexible/SocialAuth/SocialAuth.sln b/appengine/flexible/SocialAuth/SocialAuth.sln
new file mode 100644
index 0000000000..6023b07f58
--- /dev/null
+++ b/appengine/flexible/SocialAuth/SocialAuth.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocialAuth", "SocialAuth.csproj", "{416E09EE-2443-4F68-A840-07006956976E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|x64.Build.0 = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Debug|x86.Build.0 = Debug|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|x64.ActiveCfg = Release|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|x64.Build.0 = Release|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|x86.ActiveCfg = Release|Any CPU
+ {416E09EE-2443-4F68-A840-07006956976E}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal