Connecting to Active Directory - powershell-2.0

I have the following script from a book. When I try to run this, I get nothing output to the screen.
$objADSI = [adsi]""
$domain = $objADSI.distinguishedname
$userContainer = [adsi]("LDAP://cn=users," + $domain)
foreach($child in $userContainer) {
Write-Host $child.samaccountname
}
If I echo $userContainer, I get:
distinguishedName : {CN=Users,DC=company,DC=co,DC=uk}
Path : LDAP://cn=users,DC=company,DC=co,DC=uk
Do I need to run winrm quickconfig on the Active Directory server? The Active Directory server is running Windows Server 2003 standard edition. Or am I getting nothing returned for some other reason?

Change your foreach like this:
foreach($child in $userContainer.children)

Related

How to debug PowerShell process whithout error message or exception

I am trying to run the following PowerShell script from within my .NET application:
try {
Start-Process "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "--headless --disable-gpu --print-to-pdf=c:\myDir\file.pdf https://www.bing.com"
$x = "Complete"
$x | Out-File C:\myDir\error.txt
}
Catch {
$_ | Out-File C:\myDir\error.txt
}
Simply, the above will create a pdf based upon bing.com website
In my dev environment it runs fine as a PowerShell script. It also runs fine on the production server (again, as a PowerShell script).
The issue occurs when I invoke this PowerShell script from my web app on the production server. My C# code is
var command = "c:\myDir\ps.ps1";
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "powershell.exe";
psi.Arguments = command;
Process process = new Process();
process.StartInfo = psi;
process.Start();
This works fine on my dev machine. It fails on the production server. The error.txt file is written to disc which suggests it's not a permissions issue. However, the content of the error.txt file always shows "complete". It never errors.
So, it appears that the catch in the PowerShell script is never being hit. As such, no error message. There is no exception thrown in the C# code. Regardless, it isn't working.
How can I debug this?
Or, if easier, I'm happy to run the code directly instead of invoking the PowerShell script file but the following also does 'nothing'.
var command = $"\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\" -ArgumentList \"--no-sandbox --headless --disable-gpu --print-to-pdf={imagePath} {fullUrl}";
I was able to reproduce your problem. It is caused by the fact that web application on your production server is running under the user that is not currently logged in. It is running under identity of assigned application pool. Chrome has known issue of not working correctly if it's launched under the user different from currently logged user. If you check that link, you will see that issue was registered in December 2012 and still is not resolved. You could easily reproduce the problem if launch Chrome under the different user ("Run as different user" in shortcut context menu when called with pressed Shift). In this case Chrome will not open any page and will just show gray screen.
The workaround is to launch Chrome with --no-sandbox switch. Google actually does not recomment this. However if you run Chrome in automated way to access trusted source, I believe it's ok.
So to fix the problem modify start-process in the script in the following way:
start-process "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "--no-sandbox --headless --disable-gpu --print-to-pdf=c:\myDir\file.pdf https://www.bing.com"
UPDATE
I have underestimated the problem at first. Now after additional research and many tried approaches I can propose solution that works.
I didn't manage to fix your current approach of direct launch of powershell and chrome from Web Application. Chrome just fails to start and following errors appear in Event log:
Faulting application name: chrome.exe, version: 64.0.3282.186, time stamp: 0x5a8e38d5
Faulting module name: chrome_elf.dll, version: 64.0.3282.186, time stamp: 0x5a8e1e3d
Exception code: 0x80000003
Fault offset: 0x00000000000309b9
Faulting process id: 0x11524
Faulting application start time: 0x01d3bab1a89e3b4f
Faulting application path: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
Faulting module path: C:\Program Files (x86)\Google\Chrome\Application\64.0.3282.186\chrome_elf.dll
Report Id: e70a5a36-26a4-11e8-ac26-b8ca3a94ba80
This error occurrs even if you configure application pool to use identity of some existing (ordinary) user that could launch the chrome.
May be it's possible to configure IIS or application pool to prevent these errors but I have not found the way.
My proposal is to switch from starting powershell process from controller action to scheduling a task with Windows task scheduler.
Here are the steps that should be taken to accomplish this task:
On your production server create a user under which the Chrome will be started. I'll refer to created user as 'testuser'.
Login under testuser, start chrome, open some site. Without this step, the flow was not successfully, probably because of missing chrome user account.
Grant "Log on as a batch job" right for testuser. This step is required for successfull execution of scheduled tasks under testuser. The procedure is described in this answer
Add --no-sandbox argument to the script as I described in my initial answer.
Replace the code of Process.Start() with scheduling of the task job.
The easiest way to schedule a task from .Net is via TaskScheduler NuGet. Install it to your application and add following code:
string powerShellScript = #"c:\myDir\ps.ps1";
string userName = #"YOURCOMP\testuser";
string userPassword = "TestPwd123";
using (TaskService ts = new TaskService())
{
TaskDefinition td = ts.NewTask();
td.Triggers.Add(new RegistrationTrigger
{
StartBoundary = DateTime.Now,
EndBoundary = DateTime.Now.AddMinutes(1),
});
td.Settings.DeleteExpiredTaskAfter = TimeSpan.FromSeconds(5);
td.Actions.Add(new ExecAction("powershell.exe", powerShellScript));
ts.RootFolder.RegisterTaskDefinition($#"Print Pdf - {Guid.NewGuid()}", td, createType: TaskCreation.Create, userId: userName, password: userPassword, logonType: TaskLogonType.Password);
}
In above code snippet change the name and password for testuser.
With this approach your script is successfully executed and pdf is printed successfully.
Update by OP
If the above continues to fail, then again, check the Event Viewer logs. In this case, I had an issues with a message similar to The machine-default permission settings do not grant Local Activation permission for the COM Server application with CLSID {20FD4E26-8E0F-4F73-A0E0-F27B8C57BE6F} and APPID Unavailable but it was resolved by granting permissions for the CLSID. Further, try to run the task in task scheduler by itself, such as create a new task to simply launch notepad or similar to make sure that this is working with the account you want to test. In my case, I had to use the administrator account.
I think additional to what CodeFuller said having no sandbox with --no-sandbox option, you should also disable all extensions, sync and bookmarks.
The best is having a Guest session alias "browse without sign-in" with--bwsi option.
What is funny is that during testing I have found out that it is better, got better pdf printout, to disable extensions explicitly with --disable-extensions before doing --bwsi.
I have tested it and for me it works. I'm looking forward for your feedback.
Edit1 and Edit3 - removing try...catch and adding user & password and adding psuser specifics
You are probably on domain so I have adjusting the script to run as different user on domain (the user must have correct rights!)
First create your credentials file with:
Login to user e.g. psuser
Create the password file:
# Encrypt user password and save it to file
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'C:\<your_path>\your_secret_password.txt'
Then run the below improved script with encrypted credentials:
$username = 'psuser' # This needs to be adjusted to correct user you are using
$domain = <your_domain> # adjust to your needs
$encrypted_passwd = get-content 'C:\<your_path>\your_secret_password.txt' | ConvertTo-securestring
# Setting process invocation parameters.
$process_start_info = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$process_start_info.CreateNoWindow = $true
$process_start_info.UseShellExecute = $false
$process_start_info.RedirectStandardOutput = $true
$process_start_info.RedirectStandardError = $true
$process_start_info.UserName = $username
$process_start_info.Domain = $domain
$process_start_info.Password = $encrypted_passwd
$process_start_info.Verb = 'runas'
$process_start_info.FileName = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
$process_start_info.Arguments = '--no-sandbox --disable-extensions --bwsi --headless --disable-gpu --print-to-pdf=C:\prg\PowerShell\test\chrome_file.pdf https://www.bing.com'
# Creating process object.
$process = New-Object -TypeName System.Diagnostics.Process
$process.StartInfo = $process_start_info
# Start the process
[Void]$process.Start()
$process.WaitForExit()
# synchronous output - captures everything
$output = $process.StandardOutput.ReadToEnd()
$output += $process.StandardError.ReadToEnd()
Write-Output $output
During the script debugging I have encountered these errors:
a) When you want to validate against a AD server but it is not available:
Exception calling "Start" with "0" argument(s): "There are currently no logon servers available to service the logon request"
At C:\prg\PowerShell\test\chrome_print.ps1:56 char:12
+ [Void]$process.Start()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Exception calling "WaitForExit" with "0" argument(s): "No process is associated with this object."
At C:\prg\PowerShell\test\chrome_print.ps1:58 char:12
+ $process.WaitForExit()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:61 char:12
+ $output = $process.StandardOutput.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:62 char:12
+ $output += $process.StandardError.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
b) Missing domain information in the script:
Exception calling "Start" with "0" argument(s): "The stub received bad data"
At C:\prg\PowerShell\test\chrome_print.ps1:39 char:12
+ [Void]$process.Start()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Exception calling "WaitForExit" with "0" argument(s): "No process is associated with this object."
At C:\prg\PowerShell\test\chrome_print.ps1:41 char:12
+ $process.WaitForExit()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:44 char:12
+ $output = $process.StandardOutput.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:45 char:12
+ $output += $process.StandardError.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Prints the pdf
and the stderr messages:
[0313/112937.660:ERROR:gpu_process_transport_factory.cc(1009)] Lost UI shared context.
[0313/112937.662:ERROR:instance.cc(49)] Unable to locate service manifest for metrics
[0313/112937.662:ERROR:service_manager.cc(890)] Failed to resolve service name: metrics
[0313/112938.152:ERROR:instance.cc(49)] Unable to locate service manifest for metrics
[0313/112938.153:ERROR:service_manager.cc(890)] Failed to resolve service name: metrics
[0313/112942.876:INFO:headless_shell.cc(566)] Written to file C:\prg\PowerShell\test\chrom e_file.pdf.
Edit2 Adding windows account impersonation with ASP.NET
Impersonate a windows account with ASP.NET:
ASP.NET user is not passed into the new threads (by default). When you want to invoke PowerShell script it is invoked in other thread with different credentials (you can overcome that with above script when you have a dedicated domain authenticated user for running the above script). By default the script is executed under build-in account NT AUTHORITY\NETWORK SERVICE.
These steps are to overcome it on ASP.NET level:
1) Enable Windows Authentication in IIS
a) Install it first (this is windows 2008 R2 screenshot):
b) enable it on your IIS:
Change it to enabled:
2) Change your site's web.config to correctly handle impersonation
Edit the web.config file in your site’s directory. In order to execute the server side code of the current user's security context (AD).
Find the xml tag: <system.web> and add two new elements to enable the windows authentication
<authentication mode="Windows" />
<identity impersonate="True" />
3) To correctly write code to invoke in-process PowerShell script
You need to adjust your ASP.NET code in a way that you will have powershell Runspace and you will invoke the script inside the Runspace in a pipeline
A quick example:
// You need to create a Runspace. Each other pipeline you create will run in the same Runspace
// Do it only once, all others will be pipelined
RunspaceConfiguration powershellConfiguration = RunspaceConfiguration.Create();
var powershellRunspace = RunspaceFactory.CreateRunspace(powershellConfiguration);
powershellRunspace.Open();
// create a pipeline the cmdlet invocation
using ( Pipeline psPipeline = powershellRunspace.CreatePipeline() ){
// Define the command to be executed in this pipeline
Command script = new Command("PowerShell_script");
// Add any parameter(s) to the command
script.Parameters.Add("Param1", "Param1Value");
// Add it to the pipeline
psPipeline.Commands.Add(script);
try {
// Invoke() the script
var results = psPipeline.Invoke();
// work with the results
} catch (CmdletInvocationException exception) {
// Any exceptions here - for the invoked process
}
}
4) Modify aspnet.config to allow impersonation to cross threads
This step allows you to run as your current, impersonated, user.
You have to modify your servers’s aspnet.config file.
Add two xml elements to the configuration and runtime:
<configuration>
<runtime>
...
<legacyImpersonationPolicy enabled="true" />
<alwaysFlowImpersonationPolicy enabled="false" />
</runtime>
</configuration>
You have to redirect the stdin and stdout so that it sends it from powershell.exe back to the parent process (your web app). I modified your code sample to do this:
var command = "c:\myDir\ps.ps1";
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "powershell.exe";
psi.Arguments = command;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
Process process = new Process();
process.StartInfo = psi;
process.Start();
process.WaitForExit();
Console.WriteLine(process.StandardOutput);
Console.WriteLine(process.StandardError);

Knife bootstrap failing through Jenkins execute shell

I'm trying to perform a "knife bootstrap" command through Jenkins web UI execute shell, but I keep getting this error message :
(this is the knife bootstrap command I'm using) :
"knife bootstrap [the node's IP] --ssh-user ec2-user --sudo --identity-file "[my key to the node]" --node-name My123 --run-list 'role[role1]' "
and this is the error message:
" ERROR: Errno::ENOENT: No such file or directory # rb_sysopen - /etc/chef/validation.pem "
when I run the 'knife bootstrap' command directly through the CLI it works fine.
any idea why it's not working from Jenkins execute shell?
It is due to validation.pem file is missing, this is default path for validation file. Either you can set path in /chef-repo/.chef/knife.rb file or you can use default location /etc/chef/validation.pem.
You can regenerate validation key from webUI and replace the existing one, this should resolve your issue.

Invoking shell scripts on Windows under MSYS using Command

I am trying to invoke commands in Rust (1.0 beta 3) on Windows 7 in an MSYS2 environment, but I cannot understand how to do it.
Suppose that you have this very simple script called myls in your home folder:
#!/bin/bash
ls
And now create a simple program in Rust that calls the script:
use std::process::Command;
use std::path::Path;
fn main()
{
let path_linux_style = Path::new("~/myls").to_str().unwrap();
let path_win_style = Path::new("C:\\msys64\\home\\yourname\\myls").to_str().unwrap();
let out_linux = Command::new(path_linux_style).output();
let out_win = Command::new(path_win_style).output();
match out_linux
{
Ok(_) => println!("Linux path is working!"),
Err(e) => println!("Linux path is not working: {}", e)
}
match out_win
{
Ok(_) => println!("Win path is working!"),
Err(e) => println!("Win path is not working: {}", e)
}
}
Now, if you try to execute it, you will get the following output:
Linux path is not working: The system cannot find the file specified.
(os error 2)
Win path is not working: %1 is not a valid Win32 application.
(os error 193)
So I am not able to invoke any command in MSYS environment.
How can I solve it?
EDIT:
I noticed that if I invoke an executable, the problem doesn't happen, so it seems to be related to invocation of bash script. Anyway, it's quite annoying since it makes compiling projects depending on external C/C++ code (that need to launch configure script) tricky to get to work.
The Windows example doesn't work because Windows isn't a Unix. On Unix-like systems, the #! at the beginning of a script is recognized, and it invokes the executable at the given path as the interpreter. Windows doesn't have this behavior; and even if it did, it wouldn't recognize the path name to the /bin/bash, as that path name is one that msys2 emulates, it is not a native path name.
Instead, you can explicitly execute the script you want using the msys2 shell, by doing something like the following (alter the path as appropriate, I have msys32 installed since it's a 32 bit VM)
let out_win = Command::new("C:\\msys32\\usr\\bin\\sh.exe")
.arg("-c")
.arg(path_win_style)
.output();

error on paypal\rest-api-sdk-php\lib\PayPal\Transport\PayPalRestCall.php

this is the code where i have problem
i had the api paypal downloasded whi composer.json
i get the error
"Notice: Use of undefined constant CURLOPT_SSLVERSION - assumed 'CURLOPT_SSLVERSION' in C:\wamp\www\Nouveau dossier\vendor\paypal\rest-api-sdk-php\lib\PayPal\Transport\PayPalRestCall.php on line 57"
<?php
use PayPal\Api\Payer;
use PayPal\Api\Details;
use PayPal\Api\Amount;
use PayPal\Api\Transaction;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
require '../src/start.php';
$payer = new Payer();
$details = new Details();
$amount= new Amount();
$transaction = new Transaction();
$payment = new Payment();
$redirectUrls = new RedirectUrls();
$payer->setPaymentMethod("paypal");
//detail
$details->setShipping('2.00')
->setTax('0.00')
->setSubtotal('20.00');
// amount
$amount->setCurrency('GBP')
->setTotal('22.00')
->setDetails($details);
// transaction
$transaction->setAmount($amount)
->setDescription('membership');
// payment
$payment->setIntent('sale')
->setPayer($payer)
->setTransactions([$transaction]);
//redirectUrls
$redirectUrls->setReturnUrl('http://localhost/Nouveau%20dossier/paypal/pay.php?approved=true')
->setCancelUrl('http://localhost/Nouveau%20dossier/paypal/pay.php?approved=false');
$payment->setRedirectUrls($redirectUrls);
try{
$payment->create($api);
}
catch (PayPal\Exception\PPConnectionException $ex) {
echo "Exception: " . $ex->getMessage() . PHP_EOL;
echo "<pre>";
var_dump($ex->getData());
exit(1);
//catch(PPConnectionException $e){
//header('Location: ../paypal/error.php');
}
//foreach($payment->getLinks() as $link){
//if($link->getRek() == 'approval_url'){
//$redirectUrl = $link->getHref();
//}
//}
//var_dump($redirectUrl);
$approvalUrl = $payment->getApprovalLink();
?>
If you are using PHP 5.1+, this error means that you do not have PHP cUrl installed (or, your php.ini is not configured to use cUrl). I was facing the same problem on my Ubuntu host and after installing cUrl and restarting the server, problem got solved. To install cUrl, type the following in your SSH console:
sudo apt-get install php5-curl
Then restart your apache server:
sudo service apache2 restart
Of course, commands will be different for different type of servers.
I had the same issue on DigitalOcean.com hosting. I just restarted the droplet and the problem went away.

RMySQL not working with a cnf file

I am trying to connect to a MySQL server through R and it works perfect with the follwoing line:
con <- dbConnect(MySQL(), user="user", password="password",dbname="dbname", host="localhost", port=3306)
But, I would like to use a cnf file so that my user/apssword credentials donot appear in my code and tried the following:
rmysql.settingsfile<-"mydefault.cnf"
rmysql.db<-"test_db"
drv<-dbDriver("MySQL")
con<-dbConnect(drv,default.file=rmysql.settingsfile,group=rmysql.db)
And this is how my cnf file looks:
[test_db]
user=user
password=password
database=dbname
host=localhost
port=3306
It is in the same folder as in my R script which is my current working directory. But, I run into the following error:
Error in mysqlNewConnection(drv, ...) :
RS-DBI driver: (Failed to connect to database: Error: Access denied for user 'ODBC'#'localhost' (using password: NO)
)
Any suggestions, please?
Thanks so much
I had this problem very recently. RMySQL looks in the root directory for these files so you need to fully qualify the location of the file. i.e.:
rmysql.settingsfile<-"/home/MD-Tech/mydefault.cnf"
or
rmysql.settingsfile<-"c:\Users\MD-Tech\rfiles\mydefault.cnf"
Two things could be going on.
The CNF file should be encrypted, password should say password = ****. The MySQL documentation shows how to create a CNF file. Below would work for your code to create the CNF
shell> mysql_config_editor set --login-path=test_db --host=localhost --user=user --password
press enter without typing password, you will be prompted to enter it
The second thing is that user = NULL and password = NULL are missing as referenced in the src_mysql documentation
rmysql.settingsfile <- "~/.mylogin.cnf"
rmysql.db <- "test_db"
drv <- dbDriver("MySQL")
con <- dbConnect(drv, default.file = rmysql.settingsfile, group = rmysql.db, user = NULL, password = NULL)
When you add these and run the code, you should be set.
Fing something working at: https://www.r-bloggers.com/mysql-and-r/
Not in configuration file... but work.
con <- dbConnect(MySQL(),
user="me", password="nuts2u",
dbname="my_db", host="localhost")
Ya, getting this setup for the first time can be like pulling cats' teeth! Here is what I did while running R on a Droplet (Ubuntu 16.04, MySQL 5.7.16).
First, make sure you can at least login successfully to MySQL through the terminal
mysql -u kevin -p
Next, run R and verify that you can login in directly with dbConnect() using a user name and password
mydb = dbConnect(drv, user='kevin', password='ilovecats', dbname='catnapdb', host='127.0.0.1', port=3306)
Edit your mysql.cnf text file and at the bottom add a new group (exact name of this file and its location will depend on operating system and versions).
[whiskerpatrol]
user = kevin
password = ilovecats
host = 127.0.0.1
port = 3306
database = catnapdb

Resources