Service account maintenance
Introduction
Service accounts are a special type of account which allow you to authenticate API calls for automated jobs such as creating your own authentication server or performing game maintenance. Previously, you could only obtain a service account by asking Improbable support to set one up for you. With the Platform SDK, you can create your own service accounts and manage them yourself.
For security reasons, service accounts usually expire. Therefore, if you have many service accounts for different uses you will probably need a script to manage them and keep them up to date. In this example, we demonstrate how to create new service accounts, remove them, and extend the duration of all your service accounts due to expire soon.
For more information on service accounts, see Service accounts.
Find out how to download the Platform SDK from the setup guide.
Example: setting up service account maintenance
1. Instantiate a client
First, instantiate a client of the ServiceAccountServiceClient
type to communicate with the service.
Use the Create
method of the ServiceAccountServiceClient
.
private static readonly ServiceAccountServiceClient ServiceAccountServiceClient = ServiceAccountServiceClient.Create();
By default, this uses your refresh token saved locally by the SpatialOS CLI. You can find your token at:
- Windows:
C:\Users\<username>\AppData\Local\.improbable\oauth2\oauth2_refresh_token\
- Mac:
~/.improbable/oauth2/oauth2_refresh_token
Since this example is intended to run as an automated task, we recommend using a service account for authentication. If you want to provide a refresh token which is not your own, you can instantiate a PlatformRefreshTokenCredential
object and supply it to Create
:
var credentialsWithProvidedToken = new PlatformRefreshTokenCredential("my_refresh_token");
private static readonly ServiceAccountServiceClient ServiceAccountServiceClient =
ServiceAccountServiceClient.Create(credentials: credentialsWithProvidedToken);
2. Create service accounts
In a Setup()
function, create some new service accounts using the CreateServiceAccount
RPC. You must provide:
- a descriptive
Name
- a
ProjectName
which determines the project the service account is associated with - a list of
Permission
s which specify what the service account can do
Optionally, you can also provide a Lifetime
which specifies when the service account will expire. If you don’t provide this, the service account will never expire unless you manually delete it.
Construct two Permission
objects to allow the service account to manage deployments: one which permits read and write access to a project defined in a variable called ProjectName
, and another which permits read access to services.
var permProject = new Permission
{
Parts = {new RepeatedField<string> {"prj", ProjectName, "*"}},
Verbs =
{
new RepeatedField<Permission.Types.Verb>
{
Permission.Types.Verb.Read,
Permission.Types.Verb.Write
}
}
};
var permServices = new Permission
{
Parts = {new RepeatedField<string> {"srv", "*"}},
Verbs =
{
new RepeatedField<Permission.Types.Verb>
{
Permission.Types.Verb.Read
}
}
};
After defining the Permission
s, construct the CreateServiceAccountRequest
and make the RPC call to CreateServiceAccount
. Basic details about the service account, for example expiry time, are viewable by other users who are part of the same project.
var resp = ServiceAccountServiceClient.CreateServiceAccount(new CreateServiceAccountRequest
{
Name = ServiceAccountName,
ProjectName = ProjectName,
Permissions = {new RepeatedField<Permission> {permProject, permServices}},
Lifetime = Duration.FromTimeSpan(new TimeSpan(1, 0, 0, 0)) // Let this service account live for one day
});
To create multiple service accounts, wrap the RPC call in a for
loop. Store the returned IDs in a list so you can manipulate the service accounts later.
private static List<long> ServiceAccountIds;
/* ... */
for (var i = 0; i < NumberOfServiceAccountsToCreate; i++)
{
var resp = ServiceAccountServiceClient.CreateServiceAccount(new CreateServiceAccountRequest
{
Name = ServiceAccountName,
ProjectName = ProjectName,
Permissions = {new RepeatedField<Permission> {perm}},
Lifetime = Duration.FromTimeSpan(new TimeSpan(1, 0, 0, 0)) // Let this service account live for one day
});
// Add the ID of the service account you just created to a List to allow for deleting it later
ServiceAccountIds.Add(resp.Id);
}
3. List your service accounts
It is often useful to list service accounts that expire soon so that you can take action and extend their lifetime before they become invalid and possibly cause unintended consequences such as a script no longer working.
Specify at what point before a service account’s expiry you want to extend it. Then specify how long you want to extend it for.
// Take action if the service account expires in fewer than two days
private const int DaysRemainingAtWhichExpiryShouldBeIncreased = 2;
// Expand a service account's lifetime by a further two days
private const int DaysToExpandServiceAccountBy = 2;
Use the ListServiceAccounts
RPC to fetch all of your service accounts associated with the project ProjectName
and filter with Where
to obtain service accounts whose expiry time is below the threshold you just defined.
var serviceAccounts = ServiceAccountServiceClient.ListServiceAccounts(new ListServiceAccountsRequest
{
ProjectName = ProjectName
})
.Where(serviceAccount => (serviceAccount.ExpirationTime.ToDateTime() - DateTime.UtcNow).TotalDays <=
DaysRemainingAtWhichExpiryShouldBeIncreased);
4. Update service accounts nearing expiry
Iterate through the service accounts nearing expiry returned from ListServiceAccounts
and use the UpdateServiceAccount
RPC to add DaysToExpandServiceAccountBy
onto the current expiry time. If you set DaysRemainingAtWhichExpiryShouldBeIncreased
to be more than one day, this should extend the expiry times of the service accounts you created in step two.
foreach (var serviceAccount in serviceAccounts)
{
// Calculate how many days it is until the service account expires
var daysUntilExpiry =
Math.Floor((serviceAccount.ExpirationTime.ToDateTime() - DateTime.UtcNow).TotalDays);
// Now extend the lifetime by increasing the expiry time relative to the current time
ServiceAccountServiceClient.UpdateServiceAccount(new UpdateServiceAccountRequest
{
Id = serviceAccount.Id,
ExpirationTime = DateTime.UtcNow.AddDays(DaysToExpandServiceAccountBy).ToTimestamp()
});
}
5. Delete service accounts
In a Cleanup()
function, delete the service accounts created in step one.
Note: By deleting a service account, any service using the invalid refresh token for authentication may behave unexpectedly.
To delete a service account, supply the service account ID to the DeleteServiceAccount
RPC. You saved a reference to every service account created in the ServiceAccountIds
list in step two.
foreach (var id in ServiceAccountIds)
{
ServiceAccountServiceClient.DeleteServiceAccount(new DeleteServiceAccountRequest
{
Id = id
});
}