Allow profile directory creation failures for Service Account scenarios (#3244)

XDG profile directory creation can fail for accounts that do not have home directories.

The module analysis was trying to persist it's cache in an XDG profile directory.
The cache is less critical than it once was, so it's reasonable to not cache if there is no good place to do so.

Fixes #3011
This commit is contained in:
Steve Lee 2017-03-05 22:05:10 -08:00 committed by Jason Shirk
parent df0a390c2c
commit a2687bfb59
3 changed files with 69 additions and 6 deletions

View File

@ -260,9 +260,16 @@ namespace System.Management.Automation
{
// create the xdg folder if needed
if (!Directory.Exists(xdgDataHomeDefault))
{
try
{
Directory.CreateDirectory(xdgDataHomeDefault);
}
catch (UnauthorizedAccessException)
{
//service accounts won't have permission to create user folder
}
}
return xdgDataHomeDefault;
}
else
@ -276,9 +283,16 @@ namespace System.Management.Automation
{
//xdg values have not been set
if (!Directory.Exists(xdgModuleDefault)) //module folder not always guaranteed to exist
{
try
{
Directory.CreateDirectory(xdgModuleDefault);
}
catch (UnauthorizedAccessException)
{
//service accounts won't have permission to create user folder
}
}
return xdgModuleDefault;
}
else
@ -295,9 +309,16 @@ namespace System.Management.Automation
{
//xdg values have not been set
if (!Directory.Exists(xdgCacheDefault)) //module folder not always guaranteed to exist
{
try
{
Directory.CreateDirectory(xdgCacheDefault);
}
catch (UnauthorizedAccessException)
{
//service accounts won't have permission to create user folder
}
}
return xdgCacheDefault;
}
@ -305,9 +326,16 @@ namespace System.Management.Automation
else
{
if (!Directory.Exists(Path.Combine(xdgcachehome, "powershell")))
{
try
{
Directory.CreateDirectory(Path.Combine(xdgcachehome, "powershell"));
}
catch (UnauthorizedAccessException)
{
//service accounts won't have permission to create user folder
}
}
return Path.Combine(xdgcachehome, "powershell");
}

View File

@ -618,6 +618,8 @@ namespace System.Management.Automation
private int _saveCacheToDiskQueued;
private bool _saveCacheToDisk = true;
public void QueueSerialization()
{
// We expect many modules to rapidly call for serialization.
@ -625,7 +627,7 @@ namespace System.Management.Automation
// after it seems like we've stopped adding stuff to write out. This is
// avoids blocking the pipeline thread waiting for the write to finish.
// We want to make sure we only queue one task.
if (Interlocked.Increment(ref _saveCacheToDiskQueued) == 1)
if (_saveCacheToDisk && Interlocked.Increment(ref _saveCacheToDiskQueued) == 1)
{
Task.Run(async delegate
{
@ -694,6 +696,8 @@ namespace System.Management.Automation
private void Serialize(string filename)
{
AnalysisCacheData fromOtherProcess = null;
Diagnostics.Assert(_saveCacheToDisk != false, "Serialize should never be called without going through QueueSerialization which has a check");
try
{
if (Utils.NativeFileExists(filename))
@ -709,9 +713,18 @@ namespace System.Management.Automation
// Make sure the folder exists
var folder = Path.GetDirectoryName(filename);
if (!Directory.Exists(folder))
{
try
{
Directory.CreateDirectory(folder);
}
catch (UnauthorizedAccessException)
{
// service accounts won't be able to create directory
_saveCacheToDisk = false;
return;
}
}
}
}
catch (Exception e)

View File

@ -381,6 +381,28 @@ foo
}
}
}
Context "Data, Config, and Cache locations" {
BeforeEach {
$XDG_CACHE_HOME = $env:XDG_CACHE_HOME
$XDG_DATA_HOME = $env:XDG_DATA_HOME
$XDG_CONFIG_HOME = $env:XDG_CONFIG_HOME
}
AfterEach {
$env:XDG_CACHE_HOME = $XDG_CACHE_HOME
$env:XDG_DATA_HOME = $XDG_DATA_HOME
$env:XDG_CONFIG_HOME = $XDG_CONFIG_HOME
}
It "Should start if Data, Config, and Cache location is not accessible" -skip:($IsWindows) {
$env:XDG_CACHE_HOME = "/dev/cpu"
$env:XDG_DATA_HOME = "/dev/cpu"
$env:XDG_CONFIG_HOME = "/dev/cpu"
$output = & powershell -noprofile -Command { (get-command).count }
[int]$output | Should BeGreaterThan 0
}
}
}
Describe "Console host api tests" -Tag CI {