Can't find my Rackspace cloud server via openstacknetsdk - c#

I'm attempting to write a simple proof-of-concept for manipulating cloud servers in my Rackspace Cloud account via the C# openstacknetsdk library, v1.3.0.0.
The problem I'm having is although I appear to be able to authenticate successfully using my Rackspace username and API key, the API is behaving as though I don't have any servers. My code:
using net.openstack.Providers.Rackspace;
using net.openstack.Core.Providers;
using net.openstack.Core.Exceptions.Response;
using net.openstack.Providers.Rackspace.Objects;
using net.openstack.Core.Domain;
...
const string USERNAME = "[my rackspace username]";
const string API_KEY = "[my rackspace API key]";
static void Main(string[] args)
{
CloudIdentity cloudIdentity = new CloudIdentity() { APIKey = API_KEY, Username = USERNAME };
CloudServersProvider provider = new CloudServersProvider(cloudIdentity);
IEnumerable<SimpleServer> servers = provider.ListServers();
foreach (SimpleServer server in servers)
{
Console.Out.WriteLine(server.Id);
}
}
When I step through this code in the debugger, I can see that servers ends up having size 0, and nothing ends up getting written out.
This is unexpected, because I do have one server created, which I can see on the Rackspace cloud control panel website. The server is in Active status.
If I try to get information on my specific server, using the server ID from the Cloud Servers > Server Details page on the Rackspace cloud control panel site:
Server server = provider.GetDetails("[my cloud server ID]");
Console.Out.WriteLine(server.Image.Name);
I get a net.openstack.Core.Exceptions.Response.ItemNotFoundException.
The authentication seems to be working because if I intentionally change my API_KEY value to something incorrect (like "test"), I get a UserNotAuthorizedException instead.
What am I missing here? Why is the openstacknetsdk acting like I don't have any servers?

Is the server you have created in your default region?
To be safe, try specifying the region in the .ListServers() method call.
Also; you can download sample data via NuGet; search for "openstack sample".

Related

Service account is not authorized to manage project

I recently joined a team, and am adding Android Management Api to the already existing project. I added the management API, created service accounts with permissions, and am writing the .NET project to test it out.
I made a service account with Android Management User and Owner permissions. However, when I try to use the .NET library to make an enterprise, I get
The service androidmanagement has thrown an exception. HttpStatusCode is Forbidden. Caller is not authorized to manage project.
If it helps:
The API key I'm using is allowed to call any API, and the application name is a temporary one that does NOT match the project name. As for the service account with private key, I am using a FileStream to read a .json file downloaded when the service account was created.
This is my code, based on the sample app https://developers.google.com/android/management/sample-app
The error gets thrown on the createRequst.Execute()
string CreateEnterprise()
{
SignupUrlsResource.CreateRequest signupUrlRequest = managementService.SignupUrls.Create();
signupUrlRequest.ProjectId = cloud_project_id;
signupUrlRequest.CallbackUrl = "https://www.yahoo.com";
var signupUrl = signupUrlRequest.Execute();
string enterpriseToken = signupUrl.Url;
Console.WriteLine("Signup: " + enterpriseToken);
EnterprisesResource.CreateRequest createRequest = managementService.Enterprises.Create(new Enterprise());
createRequest.ProjectId = "Test Project";
createRequest.SignupUrlName = signupUrl.Name;
createRequest.EnterpriseToken = enterpriseToken;
var enterprise = createRequest.Execute();
return enterprise.Name;
}
Turns out the createRequest.ProjectId must match the project name that has the Android Management API, aka the project I'm working with.

Cross Account Access to DynamoDb tables C#

I have been dealing with this issue for which I am not able to find solution online anywhere.
I have a code which connects to AWS DynmoDb and performs read/write operations on one or more tables. This worked fine as long as my code and the DynamoDb table are in the same AWS account. Also the code uses the IAM Role attached to the Web Server. The role as all the necessary permissions assigned to it.
private AmazonDynamoDBClient GetDbClient(int ConnectionTimeOut, int ReadWriteTimeOut, int MaxRetry)
{
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig
{
Timeout = TimeSpan.FromMilliseconds(ConnectionTimeOut),
ReadWriteTimeout = TimeSpan.FromMilliseconds(ReadWriteTimeOut),
MaxErrorRetry = MaxRetry
};
return new AmazonDynamoDBClient(clientConfig);
}
Recently I need to move my code to different AWS account and things started going crazy.
Following steps I have already taken.
VPC Peering done between the VPC in the old AWS account and the new AWS account.
Cross account permissions on the DynamobDb tables are given to the role which is used by the Web server on the new AWS Account.
With this change, I do not see any more permission errors but the code tries to look for the table on the new AWS account.
It is clear in the code that AWS AccountId is not used anywhere while creating AWS DynamoDb client. So I assume that I should be able to tell the code where to look for DynamoDb table. But the C# SDK of DynamoDb does not have any provision where I can provide AWS AccountId while creating DynamoDb client.
So my issue here is related to C# code to connect to DynamoDb service and not the IAM roles and permissions on AWS (for this I am able to fine plenty of solution).
Found this question aws cross account dynamodb access with IAM role with similar issue but it does not suggest the fix to do in the code.
One way to proceed is to use Security Token Service. First you need to assume a role and get temporary credentials:
Credentials GetCredentials(String roleArn)
{
using (var stsClient = new AmazonSecurityTokenServiceClient())
{
try
{
var response = stsClient.AssumeRole(new AssumeRoleRequest(roleARN));
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) return response.Credentials;
}
catch (AmazonSecurityTokenServiceException ex)
{
return null;
}
}
}
You can then use the credentials to initiate your DynamoDB client.
See another example here.
The AWS SDK and CLI (whether it's running locally or on (say) an EC2 instance) looks in the following locations for credentials:
Command line options
Environment variables
CLI credentials file
CLI configuration file
Container credentials
Instance profile credentials
If you have a credentials file configured, then, assuming we're running under the default profile, this will indirectly define the account under which it is running via the access key provided.
You can also define AWS-specific environment variables, such as AWS_ACCESS_KEY_ID which take precedence over the credentials file.
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html

Firestore C#: Missing or insufficient permissions

I am currently exploring Firebase's Cloud Firestore in C# and has encountered with the error which I could not resolve after searching SO. It seems that the resources for Firestore in C# is quite limited:
"Status(StatusCode=PermissionDenied, Detail=\"Missing or insufficient permissions.\")"
My code so far:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "FirebaseCsharpTest.json");
string project = "MyProjectId";
FirestoreDb db = FirestoreDb.Create(project);
Console.WriteLine("Created Cloud Firestore client with project ID: {0}", project);
AddPerson(db).GetAwaiter().GetResult();
}
public static async Task AddPerson(FirestoreDb db)
{
CollectionReference collection = db.Collection("users");
DocumentReference document = await collection.AddAsync(new
{
Name = new
{ First = "Ada", Last = "Lovelace" },
Born = 1815
});
}
}
I have checked on my Firebase console that the Firestore security rules are set to public (as of now, for testing sake). I have also ensured that the authentication json file is the right file generated from Google Developer Console as suggested in this post.
Is there something I'm missing?
EDIT:
My permissions on google cloud console:
Do check the projectID that you have been adding.
ProjectID is supposed to be the one that is specified in your json file.
This is a Cloud IAM issue and not a security rule issues. The C# server client library creates a privileged server environment that doesn't take into account Cloud Firestore security rules.. It seems that either your key file's service account doesn't have the correct IAM role or your code is not finding your keyfile.
Try using the full path to your keyfile instead of the relative path.
You can also try setting up a new service account and key file as described here.
Also, make sure you are changing the project variable:
string project = "NewFirebaseCsharpTest";
FirestoreDb db = FirestoreDb.Create(project);
Change the string project to the Id of the project and not the name of the project. The Id will probably start with the name and have a numeric suffix.
If that fails, go to the Log Explorer and query the logs. You will see an error that explains why your permission was denied.
You're never going to get enough information from the client-side for security reasons. Google isn't going to tell someone trying to gain access to something they shouldn't have access to what is going wrong. But, an admin can view the logs on the other side which will log all the information.

How to Authenticate WebHDFS with c#

I have been attempting to upload files using c# into Hadoop using the WebHDFS REST API.
This code works fine:
using (var client = new System.Net.WebClient())
{
string result = client.DownloadString("http:/ /host:50070/webhdfs/v1/user/myuser/?op=LISTSTATUS");
client.DownloadFile("http:/ /host:50070/webhdfs/v1/user/myuser/tbible.txt?user.name=myuser&op=OPEN","d:\tbible.txt");
}
This code gets a 403 Forbidden:
using (var client = new System.Net.WebClient())
{
client.UploadFile("http:/ /host:50070/webhdfs/v1/user/myuser/?user.name=myuser&op=CREATE", "PUT", "d:\bible.txt");
}
I have tried adding a network credential, with no luck.
How do I authenticate to our Cluster from .NET? The Cluster is Hortonworks HDP1.3 on RHEL5.
(The extra spaces in this post are to keep http:/ / from being a link)
Also, I would have liked to use Microsoft's hadoop SDK, but it is alpha and wont compile in my environment :(
Make sure that you are writing to a directory that is under the group which WebHDFS operates under. By default this is hdfs.
A quick way to check this doing hadoop fs -ls on the directory's parent directory to get the group permission settings (the second column that may look like a username).

Change remote password (in code, .Net 3.5)

Due to our clients authentication and network topology we have a number of Windows Servers in a DMZ without Active Directory or a Domain Controller. Corporate policy stipulates that passwords must change once a month. Our dev machines are in AD (not in the DMZ) so we run into the situation that we have to synchronise our usernames and passwords on each of the DMZ machines with our AD credentials every month. There are a lot of DMZ machines.
I want to use a simple console app to change the user passwords on all the DMZ machines for a given user. So far, I have the following code:
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
class Program{
static void Main(){
List<string> remoteHosts = new List<string> { "RemoteHostA", "RemoteHostB", "RemoteHostC" };
remoteHosts.ForEach(host => ChangePassword(host, "username", "oldPassword", "newPassword"));
}
static void ChangePassword(string host, string username, string oldPassword, string newPassword){
using (var context = new PrincipalContext(ContextType.Machine, host, username, newPassword))
using (var user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username))
user.ChangePassword(oldPassword, newPassword);
}
}
The problem is that this only works if the password has not already changed on the dev machine where it is being run from. Because the context that is used, first has to authenticate with the dev machine in order to gain access to the network, then it has to gain access to the remote (DMZ) machine using the same context before changing the password.
How can I alter the method to use a new-password-context to gain access to the network and an old-password-context to gain access to the remote host?
Note to Title Editors: The code depends on System.DirectoryServices.AccountManagement which is an FX 3.5 assembly not 3.0.
Can you use WMI directly to achieve this? A quick search showed up this page
Note : It is a long time since I did anything with WMI, but I do remember being able to call it from a C# app, if that's how you are comfortable using it. (Check in System.Management)

Categories