can not connect Azure SQL with Azure AD user in Azure - powershell

I have a powershell script used to query Azure SQL database with Azure AD user. I can run the poweshell script on my local machine. But when I host the powershell script on Azure function, I always get the error : keyword not supported: 'authentication'
My script
$Username = “”
$Password = “”
$Port = 1433
$cxnString = "Server=tcp:$serverName,$Port;Database=$databaseName;UID=$UserName;PWD=$Password;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;Authentication=Active Directory Password"
$query = ''
Invoke-Sqlcmd -ConnectionString $cxnString - Query $query

According to my test, now we can not implement it with PowerShell in Azure Function. Now we can implement it with .Net Core Function. We need to package Microsoft.Data.SqlClient
For example
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
string userName = "<>";
string password = "<>";
string server = "<>.database.windows.net";
string database = "test";
builder.ConnectionString = "Server=tcp:" + server + ",1433;Initial Catalog=" + database + ";Authentication=Active Directory Password;User ID=" + userName + ";Password=" + password + ";MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;";
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
string sql = "SELECT * FROM StarWars";
using (SqlCommand command = new SqlCommand(sql, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
log.LogInformation(reader.GetString(2));
}
}
}
}

Related

Create a Azure PostgreSQL schema using terraform on a Azure PostgreSQL Database

I am able to create a azurerm_postgresql_flexible_server and azurerm_postgresql_flexible_server_database using terraform.
I am not able to create a schema using TF but not able to get much help on documentation.
I also checked https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs/resources/postgresql_schema
but that uses a different provider. I am not sure what am I missing here.
This is the TF template which creates the Azure PostgreSQL server and DB -
module "common_modules" {
source = "../modules/Main"
}
provider "azurerm" {
features {}
}
locals {
#Construct Tag Data for Resource
resourceTags = {
environment = var.environment
createdBy = var.createdBy
managedBy = var.managedBy
colorBand = var.colorBand
purpose = var.purpose
lastUpdateOn = formatdate("DD-MM-YYYY hh:mm:ss ZZZ", timestamp())
}
}
resource "azurerm_postgresql_flexible_server" "postgreSQL" {
name = var.postgreSQL
location = var.location
resource_group_name = var.ckeditorResorceGroup
administrator_login = var.postgreSQLAdmin
administrator_password = var.password
sku_name = "B_Standard_B1ms"
version = "13"
storage_mb = 32768
backup_retention_days = 7
geo_redundant_backup_enabled = false
tags = local.resourceTags
}
resource "azurerm_postgresql_flexible_server_database" "postgreSQLDB" {
name = var.postgreSQLDB
server_id = azurerm_postgresql_flexible_server.postgreSQL.id
collation = "en_US.utf8"
charset = "utf8"
}
resource "azurerm_postgresql_flexible_server_firewall_rule" "postgreSQLFirewallRule" {
name = "allow_access_to_azure_services"
server_id = azurerm_postgresql_flexible_server.postgreSQL.id
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
have a look at https://registry.terraform.io/providers/cyrilgdn/postgresql or https://github.com/cyrilgdn/terraform-provider-postgresql
usable, but you need network connectivity to resolve names (azure private dns zone) and to connect with postgresql flexible server. The terraform code should run in same vnet like flexi server.

Run custom Powershell script on provisioned Azure VM

I provisioned VM with following C# snippet
var ssrsVm = new WindowsVirtualMachine("vmssrs001", new WindowsVirtualMachineArgs
{
Name = "vmssrs001",
ResourceGroupName = resourceGroup.Name,
NetworkInterfaceIds = { nic.Id },
Size = "Standard_B1ms",
AdminUsername = ssrsLogin,
AdminPassword = ssrsPassword,
SourceImageReference = new WindowsVirtualMachineSourceImageReferenceArgs
{
Publisher = "microsoftpowerbi",
Offer = "ssrs-2016",
Sku = "dev-rs-only",
Version = "latest"
},
OsDisk = new WindowsVirtualMachineOsDiskArgs
{
Name = "vmssrs001disk",
Caching = "ReadWrite",
DiskSizeGb = 200,
StorageAccountType = "Standard_LRS",
}
});
After VM has been provisioned I would like to run a custom Powershell script on it to add a firewall rule. Now wondering how to do this as a part of the Pulumi app.
With Azure looks like I could do this with RunPowerShellScript but couldn't find anything about it in Pulumi docs, maybe there is a better way to handle my case?
UPDATE
Thanks to Ash's comment I was able to find VirtualMachineRunCommandByVirtualMachine which seems should do what I'm looking for, but unfortunately, following code snippet returns error
var virtualMachineRunCommandByVirtualMachine = new VirtualMachineRunCommandByVirtualMachine("vmssrs001-script",
new VirtualMachineRunCommandByVirtualMachineArgs
{
ResourceGroupName = resourceGroup.Name,
VmName = ssrsVm.Name,
RunAsUser = ssrsLogin,
RunAsPassword = ssrsPassword,
RunCommandName = "enable firewall rule for ssrs",
Source = new VirtualMachineRunCommandScriptSourceArgs
{
Script =
#"Firewall AllowHttpForSSRS
{
Name = 'AllowHTTPForSSRS'
DisplayName = 'AllowHTTPForSSRS'
Group = 'PT Rule Group'
Ensure = 'Present'
Enabled = 'True'
Profile = 'Public'
Direction = 'Inbound'
LocalPort = ('80')
Protocol = 'TCP'
Description = 'Firewall Rule for SSRS HTTP'
}"
}
});
error
The property 'runCommands' is not valid because the 'Microsoft .Compute/RunCommandPreview' feature is not enabled for this subscription."
Looks like other people are struggling with the same here.
You can use a Compute Extension to execute a script against a VM with Pulumi.
This article details some of the options if you just completed the procedure via PowerShell.
As an addition to Ash answer here is how I integrated it with Pulumi
first, I create a blob container for my project scripts
var deploymentContainer = new BlobContainer("deploymentscripts", new BlobContainerArgs
{
ContainerName = "deploymentscripts",
ResourceGroupName = resourceGroup.Name,
AccountName = storageAccount.Name,
});
next, I upload all of my Powershell scripts to create blob
with this snippet
foreach (var file in Directory.EnumerateFiles(Path.Combine(Environment.CurrentDirectory, "Scripts")))
{
var fileName = Path.GetFileName(file);
var blob = new Blob(fileName, new BlobArgs
{
ResourceGroupName = resourceGroup.Name,
AccountName = storageAccount.Name,
ContainerName = deploymentContainer.Name,
Source = new FileAsset(file),
});
deploymentFiles[fileName] = SignedBlobReadUrl(blob, deploymentContainer, storageAccount, resourceGroup);
}
SignedBlobReadUrl grabbed from Pulumi repo.
private static Output<string> SignedBlobReadUrl(Blob blob, BlobContainer container, StorageAccount account, ResourceGroup resourceGroup)
{
return Output.Tuple<string, string, string, string>(
blob.Name, container.Name, account.Name, resourceGroup.Name).Apply(t =>
{
(string blobName, string containerName, string accountName, string resourceGroupName) = t;
var blobSAS = ListStorageAccountServiceSAS.InvokeAsync(new ListStorageAccountServiceSASArgs
{
AccountName = accountName,
Protocols = HttpProtocol.Https,
SharedAccessStartTime = "2021-01-01",
SharedAccessExpiryTime = "2030-01-01",
Resource = SignedResource.C,
ResourceGroupName = resourceGroupName,
Permissions = Permissions.R,
CanonicalizedResource = "/blob/" + accountName + "/" + containerName,
CacheControl = "max-age=5",
});
return Output.Format($"https://{accountName}.blob.core.windows.net/{containerName}/{blobName}?{blobSAS.Result.ServiceSasToken}");
});
}
and lastly, I create Extension to run my script
code
var extension = new Extension("ssrsvmscript", new Pulumi.Azure.Compute.ExtensionArgs
{
Name = "ssrsvmscript",
VirtualMachineId = ssrsVm.Id,
Publisher = "Microsoft.Compute",
Type = "CustomScriptExtension",
TypeHandlerVersion = "1.10",
Settings = deploymentFiles["ssrsvm.ps1"].Apply(script => #" {
""commandToExecute"": ""powershell -ExecutionPolicy Unrestricted -File ssrsvm.ps1"",
""fileUris"": [" + "\"" + script + "\"" + "]}")
});
Hope that will save some time someone else struggling with the problem.

How to connect to heroku postgress database from JDBC?

I use this code
But can anyone suggest me or guide me to a right document which can give me an example of how to connect to heroku postgress database with JDBC ?
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() +
dbUri.getPath();
connectionPool = new BasicDataSource();
if (dbUri.getUserInfo() != null) {
connectionPool.setUsername(dbUri.getUserInfo().split(":")[0]);
connectionPool.setPassword(dbUri.getUserInfo().split(":")[1]);
}
connectionPool.setDriverClassName("org.postgresql.Driver");
connectionPool.setUrl(dbUrl);
connectionPool.setInitialSize(1);
Connection connection = connectionPool.getConnection();
See heroku's documentation
Note:
The DATABASE_URL for the Heroku Postgres add-on follows the below convention
postgres://<username>:<password>#<host>:<port>/<dbname>
However the Postgres JDBC driver uses the following convention:
jdbc:postgresql://<host>:<port>/<dbname>?user=<username>&password=<password>
Sample code to parse DATABASE_URL into Jdbc format:
private static Connection getConnection() throws URISyntaxException, SQLException {
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath();
return DriverManager.getConnection(dbUrl, username, password);
}

Crystal Reports asks password in Client systems

This is the Login Info Method
private void SetLogonInfo()
{
try
{
LogInfo.ConnectionInfo.ServerName = "ServerName";
LogInfo.ConnectionInfo.UserID = "UserID";
LogInfo.ConnectionInfo.Password = "Password";
LogInfo.ConnectionInfo.DatabaseName = "DataBase";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
To create report I used this code
crystalReportViewer1.ReportSource = null;
rptdoc = new ReportDocument();
rptdoc.Load("REPORTS\\TC.rpt");
crystalReportViewer1.SelectionFormula =selectionFormula;
crystalReportViewer1.ReportSource = rptdoc;
rptdoc.Database.Tables[0].ApplyLogOnInfo(LogInfo);
It works well in server system, but if I use this in client systems, it asks for username and password. I'm using Crystal Reports 10. Moreover sometimes it asks for Username password in server system also. How to resolve this?
You're doing things in the wrong order. You need to do the login programmatically BEFORE you load the report on the viewer.
Additionally, I cannot stress enough that you need to test your program on the server machine and a test client machine before you release it to users.
The reason for this error is wrong username, password.
Check username, password and use the code below:
ReportDocument cryRpt = new ReportDocument();
TableLogOnInfos crtableLogoninfos = new TableLogOnInfos();
TableLogOnInfo crtableLogoninfo = new TableLogOnInfo();
ConnectionInfo crConnectionInfo = new ConnectionInfo();
Tables CrTables;
//This is for Access Database
crConnectionInfo.ServerName = "" + "" +Application.StartupPath + "\\Database.mdb"; //access Db Path
crConnectionInfo.DatabaseName = "" + "" + Application.StartupPath + "\\Database.mdb";//access Db Path
crConnectionInfo.UserID = "ADMIN";
crConnectionInfo.Password = Program.DBPassword; //access password
//This is for Sql Server
crConnectionInfo.UserID = Program.Severuser; //username
crConnectionInfo.Password = Program.Password;//password
crConnectionInfo.ServerName = Program.server;//servername
crConnectionInfo.DatabaseName = Program.database;//database
string path = "" + Application.StartupPath + "\\supportingfiles\\Invoice.rpt";
cryRpt.Load(path);
CrTables = cryRpt.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables)
{
crtableLogoninfo = CrTable.LogOnInfo;
crtableLogoninfo.ConnectionInfo = crConnectionInfo;
CrTable.ApplyLogOnInfo(crtableLogoninfo);
}
cryRpt.SetParameterValue("invoiceno", Program.billno);
crystalReportViewer1.ReportSource = cryRpt;
crystalReportViewer1.Refresh();

how to establish and enter a remote session using runspace in powershell

I am trying to establish a session with a remote host B from my machine A, within a C# code. I am using runspace API for that. the code snippet is provided below
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
//constructing the vmname parameter here
vmname = useralias + DateTime.Now.ToString();
Pipeline pipeline = runspace.CreatePipeline();
string scripttext = "$secpasswd = ConvertTo-SecureString '222_bbbb' -AsPlainText –Force";
string scripttext1 = "$mycreds = New-object -typename System.Management.Automation.PSCredential('TS-TEST-09\\Administrator',$secpasswd)";
string scripttext2 = "$s = New-PSSession -ComputerName TS-TEST-09 -Credential $mycreds";
//not accepting session string here, only computername acceptable
**string scripttext3 = "Enter-PSSession -Session $s";**
//Command cmd = new Command(#"C:\mypath\helper.ps1", true);
//cmd.Parameters.Add("local_useralias", useralias);
//cmd.Parameters.Add("local_vmname", vmname);
//cmd.Parameters.Add("local_datastore", datastoredropdown.Text.ToString());
//cmd.Parameters.Add("local_architecture", architecturedropdown.Text.ToString());
pipeline.Commands.AddScript(scripttext);
pipeline.Commands.AddScript(scripttext1);
pipeline.Commands.AddScript(scripttext2);
pipeline.Commands.AddScript(scripttext3);
//pipeline.Commands.Add(cmd);
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
this code is expected to enter into a session with machine TS-TEST-09 and invoke the script helper.ps1 existing on that machine(that part is commented out in the code currently as i am not able to enter into the session with remote host).
now the problem is that i can't enter into the session $s using -Session parameter(highlighted at scripttext3) however i can enter into it using -Computername parameter.
the error that i get when using -Session parameter in scripttext3 is :
at
invokedSystem.Management.Automation.Internal.Host.InteralHost.GetIHostSupportsInteractiveSession()
at invokedSystem.Management.Automation.
Internal.Host.InteralHost.PushRunspace(Runspace runspace)
at Microsoft.Powershel.Commands.EnterPSSessionCommand.ProcessRecord()
at System.Management.Automation.Cmdlet.DoProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
end of inner exception stack trace
does it mean i have to write a custom PSHost and add support for the Enter-PSSession cmdlet with this parameter?
Is there any alternative to make this command work?
any help will be much appreciated.
Thanks,
Manish
The easiest way to open a remote session goes something like this:
string shell = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
var target = new Uri("http://myserver/wsman");
var secured = new SecureString();
foreach (char letter in "mypassword")
{
secured.AppendChar(letter);
}
secured.MakeReadOnly();
var credential = new PSCredential("username", secured);
var connectionInfo = new WSManConnectionInfo(target, shell, credential);
Runspace remote = RunspaceFactory.CreateRunspace(connectionInfo);
remote.Open();
using (var ps = PowerShell.Create())
{
ps.Runspace = remote;
ps.Commands.AddCommand("'This is running on {0}.' -f (hostname)");
Collection<PSObject> output = ps.Invoke();
}
You could also create remote pipelines from the remote runspace instance, but the new PowerShell object is a much more managable way to do this (since powershell v2.)
In powershell v3, you can just new up a WSManConnectionInfo and set the ComputerName property as the other properties adopt the same defaults as the above. Unfortunately these properties are read-only in v2 and you have to pass in the minimum as above. Other variants of the constructor will let you use kerberos/negotiate/credssp etc for authentication.
-Oisin
I wanted to leave a comment on the solution, as it helped me alot as well,
but one thing i was missing was the port for WSMan which is 5985
so this
var target = new Uri("http://myserver/wsman");
should be
var target = new Uri("http://myserver:5895/wsman");
in my case
Have you tried Invoke-Command? Enter-PsSession is there for interactive use. (see help Enter-PsSession -online).