LibGit2Sharp how to push with kerberos authentication? - kerberos

I need to push branches from a Intranet application (Windows environment). Some users from one team can do this action. The Git local repository is hosted on the web server and the remote on another server. URL protocol is https and we use Kerberos authentication. I don't want the application's users enter their Windows userid and password.
So, as an initialization step, I configure the local repository according to the user:
var m_Repo = new Repository(repoFldPathName);
Configuration config = m_Repo.Config;
config.Set<string>("user.name", m_UserName);
config.Set<string>("http.sslVerify", "false");
string url = string.Format(https://{0}#my-host.fr/folder/repo_name.git, m_UserName);
Remote remote = m_Repo.Network.Remotes["origin"];
if (remote != null)
{
if (remote.Url != url)
{
m_Repo.Network.Remotes.Remove("origin");
m_Repo.Network.Remotes.Add("origin", url);
}
}
else
m_Repo.Network.Remotes.Add("origin", url);
And when it's time to push the branch "master" I prepare the push (as I seen on another post):
PushOptions options = new PushOptions();
Remote remote = m_Repo.Network.Remotes["origin"];
Branch branch = m_Repo.Branches["master"];
if (branch.Remote == null)
m_Repo.Branches.Update(branch,
b => b.Remote = remote.Name,
b => b.UpstreamBranch = branch.CanonicalName);
options.CredentialsProvider = (_url, _user, _cred) => new DefaultCredentials();
m_Repo.Network.Push(branch, options);
And after few minutes of execution, I get this exception :
LibGit2Sharp.LibGit2SharpException was unhandled by user code
HResult=-2146233088
Message=Failed to receive response: La requête doit être renvoyée
Source=LibGit2Sharp
StackTrace:
à LibGit2Sharp.Core.Ensure.HandleError(Int32 result)
à LibGit2Sharp.Core.Ensure.ZeroResult(Int32 result)
à LibGit2Sharp.Core.Proxy.git_remote_push(RemoteSafeHandle remote, IEnumerable`1 refSpecs, GitPushOptions opts, Signature signature, String reflogMessage)
à LibGit2Sharp.Network.Push(Remote remote, IEnumerable`1 pushRefSpecs, PushOptions pushOptions, Signature signature, String logMessage)
à LibGit2Sharp.Network.Push(Remote remote, String pushRefSpec, PushOptions pushOptions, Signature signature, String logMessage)
à LibGit2Sharp.NetworkExtensions.Push(Network network, IEnumerable`1 branches, PushOptions pushOptions)
à LibGit2Sharp.NetworkExtensions.Push(Network network, Branch branch, PushOptions pushOptions)
à CDM.ESD1_WSGINSTALL.Business.GitRepo.Push(brEnum brName) dans c:\PRIV\Projects\ESD1\ESD1_WSGINSTALL\ESD1_WSGINSTALL.Business\GitRepo.cs:ligne 72
à CDM.ESD1WSGINSTALL.Commands.CharteView.DoBuildRPM(String id) dans c:\PRIV\Projects\ESD1\ESD1_WSGINSTALL\ESD1_WSGINSTALL\App_Code\Commands\CharteViewActivity\CharteView.cs:ligne 262
InnerException:
Thanks for your help

I think the DefaultCredentials type is what you're after.
As stated by the xml documentation, it's "A credential object that will provide the "default" credentials (logged-in user information) via NTLM or SPNEGO authentication."
Settings the PushOptions.CredentialsProvider to the following should do the trick
CredentialsProvider = (_url, _user, _cred) => new DefaultCredentials()
Update
When I use Git Extensions on my Windows machine to push a branch, (git push origin master --tag) a "OpenSSH" popup claims my password
Sadly, LibGit2Sharp doesn't support SSH yet. I'd suggest you to subscribe to the open issue #852 to get notified about its progress.

Related

Using Nuget.Protocol to delete a package from Azure DevOps

I'm writing a simple application to implement package retention in our AzureDevOps NuGet feed, but I can't delete a package -- nothing happens.
(I want to keep all release packages, but delete all pre-release packages for branches that nolonger exist and keep only the latest three pre-release packages for branches that do exist.)
// Log in and whatnot.
PackageSource packageSource = new PackageSource("https://pkgs.dev.azure.com/Organisation/_packaging/Organisation/nuget/v3/index.json")
{
Credentials = new PackageSourceCredential(
source: "https://pkgs.dev.azure.com/Organisation/_packaging/Organisation/nuget/v3/index.json",
username: "rwb#organisation.co.uk",
passwordText: _Pat,
isPasswordClearText: true,
validAuthenticationTypesText: null)
};
NuGet.Protocol.Core.Types.SourceRepository repository = NuGet.Protocol.Core.Types.Repository.Factory.GetCoreV3(packageSource);
PackageSearchResource packageSearch = repository.GetResourceAsync<NuGet.Protocol.Core.Types.PackageSearchResource>().Result;
PackageUpdateResource packageUpdate = repository.GetResourceAsync<PackageUpdateResource>().Result;
// Delete a package -- doesn't work!
packageUpdate.Delete("Organisation.MyDll", "1.0.1-branch.build", packageSource => _Pat, packageSource => true, false, _Logger);
The .Delete doesn't throw an exception or log any error, but the package remains in AzureDevOps.
I think I need to add .Wait() because of the async nonsense, but even so: the packages appear srikethrough in the Azure DevOps website, but not in the feed's recycle bin, and they're still listed in NuGet package manager in VisualStudio.
How do you actually delete the things?
Update
So apparently the C# only delists and you have to use the HTTP API directly to actually delete. However, it's impossible to authenticate.
private static void Delete(NuGet.Packaging.Core.PackageIdentity packageIdentity)
{
// https://learn.microsoft.com/en-us/nuget/api/package-publish-resource
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("X-NuGet-ApiKey", "VSTS");
//httpClient.DefaultRequestHeaders.Add("X-NuGet-ApiKey", _Pat);
//httpClient.DefaultRequestHeaders.Add("X-NuGet-ApiKey", "rwb#organisation.co.uk:" + _Pat);
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", ":" + _Pat);
//httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", "rwb#organisation.co.uk:" + _Pat);
//httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _Pat);
// https://learn.microsoft.com/en-us/rest/api/azure/devops/artifactspackagetypes/nuget/delete-package-version?view=azure-devops-rest-6.0
HttpResponseMessage rx = httpClient.DeleteAsync($"https://pkgs.dev.azure.com/Organisation/_apis/packaging/feeds/FeedName/nuget/packages/{packageIdentity.Id}/versions/{packageIdentity.Version}?api-version=6.0-preview.1").Result;
}
I had exactly the same issue that the standard NuGet delete will only delist the package.
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", _Pat))));
What worked for me (authentication-wise) was the ToBase64String conversion.

Databricks REST API call for updating branch error : User Settings > Git Integration to set up an Azure DevOps personal access token

I am getting below error for updating the repo to a different branch using databricks rest api as mentioned at https://docs.databricks.com/dev-tools/api/latest/repos.html#operation/update-repo .
I have authenticated using service principal and generated dbrks_bearer_token and dbrks_management_token.
Please find below code for same :-
import requests
import os
import json
TOKEN_REQ_BODY = {
'grant_type': 'client_credentials',
'client_id': 'client_id',
'client_secret': 'client_secret'
}
TOKEN_BASE_URL = 'https://login.microsoftonline.com/' + 'tenant_id' + '/oauth2/token'
TOKEN_REQ_HEADERS = {'Content-Type': 'application/x-www-form-urlencoded'}
def dbrks_management_token():
TOKEN_REQ_BODY['resource'] = 'https://management.core.windows.net/'
response = requests.get(TOKEN_BASE_URL, headers=TOKEN_REQ_HEADERS, data=TOKEN_REQ_BODY)
if response.status_code == 200:
print(response.status_code)
return response.json()['access_token']
else:
raise Exception(response.text)
return response.json()['access_token']
def dbrks_bearer_token():
TOKEN_REQ_BODY['resource'] = '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d'
response = requests.get(TOKEN_BASE_URL, headers=TOKEN_REQ_HEADERS, data=TOKEN_REQ_BODY)
if response.status_code == 200:
print(response.status_code)
else:
raise Exception(response.text)
return response.json()['access_token']
DBRKS_BEARER_TOKEN = dbrks_bearer_token()
DBRKS_MANAGEMENT_TOKEN = dbrks_management_token()
DBRKS_REQ_HEADERS = {
'Authorization': 'Bearer ' + DBRKS_BEARER_TOKEN,
'X-Databricks-Azure-Workspace-Resource-Id':
'/subscriptions/susbcriptionid' +
'/resourceGroups/rg-dev/providers/Microsoft.Databricks/workspaces/dbr-dev',
'X-Databricks-Azure-SP-Management-Token': DBRKS_MANAGEMENT_TOKEN }
DBRKS_CLUSTER_ID = {'cluster_id': 'cluster_id'}
def update_repo():
DBRKS_START_ENDPOINT = 'api/2.0/repos/0328767704612345'
postjson = """{
"branch": "main"
}"""
response = requests.patch("https://adb-1234582271731234.0.azuredatabricks.net/"
+ DBRKS_START_ENDPOINT,
headers=DBRKS_REQ_HEADERS,
json=json.loads(postjson))
print(response.status_code)
if response.status_code != 200:
raise Exception(response.text)
os.environ["DBRKS_CLUSTER_ID"] = response.json()["cluster_id"]
print(response.content)
update_repo()
I am getting below error:-
Traceback (most recent call last):
File "C:/Users/IdeaProjects/DBCluster/DB_rest_api.py", line 109, in <module>
update_repo()
File "C:/Users/IdeaProjects/DBCluster/DB_rest_api.py", line 104, in update_repo
raise Exception(response.text)
Exception: {"error_code":"PERMISSION_DENIED","message":"Missing Git provider credentials. Go to User Settings > Git Integration to add your personal access token."}
403
Can someone please let me know if i need to anything explicitly at azure devops git configuration level as well?
Many thanks..!!
To do any operations with Databricks Repos, you need to set a Git personal access token. Because you're using service principal, you can't set that personal access token via UI, but you can perform setting of that Git token using recently implemented Git Credentials REST API - just do that once for your service principal (or when Git PAT expires), and then Repos operations will work.

Generate SPNEGO Token Failured

I tried to generate the token which can be used as the HTTP header to authenticate to the HDFS WebHDFS URL and Oozie REST API URL.
I referenced the url below to have the below code to generate the Negotiate token.
https://www.ibm.com/support/knowledgecenter/en/SS7JFU_8.5.5/com.ibm.websphere.express.doc/ae/tsec_SPNEGO_token.html
public class TokenCreation {
private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
public static byte[] genToken(String principal) {
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
byte[] spnegoToken = new byte[0];
try {
Oid spnegoMechOid = new Oid(SPNEGO_OID);
Oid krb5MechOid = new Oid(KERBEROS_OID);
GSSCredential clientGssCreds = null;
GSSManager manager = GSSManager.getInstance();
GSSName gssUserName = manager.createName(principal, GSSName.NT_USER_NAME, krb5MechOid);
clientGssCreds = manager.createCredential(gssUserName.canonicalize(krb5MechOid),
GSSCredential.INDEFINITE_LIFETIME,
krb5MechOid,
GSSCredential.INITIATE_ONLY);
clientGssCreds.add(gssUserName,
GSSCredential.INDEFINITE_LIFETIME,
GSSCredential.INDEFINITE_LIFETIME,
spnegoMechOid, GSSCredential.INITIATE_ONLY);
GSSName gssServerName = manager.createName(principal, GSSName.NT_USER_NAME);
GSSContext clientContext = manager.createContext(gssServerName.canonicalize(spnegoMechOid),
spnegoMechOid,
clientGssCreds,
GSSContext.DEFAULT_LIFETIME);
// optional enable GSS credential delegation
clientContext.requestCredDeleg(true);
// create a SPNEGO token for the target server
spnegoToken = clientContext.initSecContext(spnegoToken, 0, spnegoToken.length);
} catch (GSSException e) {
e.printStackTrace();
}
return spnegoToken;
}
But after running the above code, I always got the below prompt:
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.c.u.security.KrbUtils - after loginUserFromKeytab............AtoimcUser:HTTP/host1.exmaple.com#EXAMPLE.COM
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>User Name is HTTP/host1.exmaple.com#EXAMPLE.COM
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>Mode is KERBEROS
>>>KinitOptions cache name is /tmp/krb5cc_0
Kerberos username [root]: ^C^C^C
Kerberos password for root:
You can see at the end of the above output log.
The "Kerberos username" is always prompt to ask for username.
Also I have tried to manually run kinit the keytab.
and the above class can generate the token successfully.
But manually run kinit is NOT the way I wanted.
Would you please help it?
Thanks.
Kerberos and SPNEGO support in Java is cumbersome unfortunately.
I've created a small library to simplify some Kerberos use cases: https://github.com/bedrin/kerb4j
You can use it like this to generate SPNEGO token:
SpnegoClient spnegoClient = SpnegoClient.loginWithKeyTab("svc_consumer", "/opt/myapp/consumer.keytab");
URL url = new URL("http://api.provider.acme.com/api/operation1");
SpnegoContext context = spnegoClient.createContext("http://provider.acme.com"); // Will result in HTTP/provider.acme.com SPN
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader());

Authorisation issue while accessing a page from repository in CQ5.

I'm trying to hit a page which contains a xml structure. for that i'm using this code
#Reference
private SlingRepository repository;
adminSession = repository.loginAdministrative( repository.getDefaultWorkspace());
String pageUrl = "http://localhost:4504"+page+".abc.htm";
conn = (HttpURLConnection)new URL(pageUrl).openConnection();
conn.setRequestProperty("Accept-Charset", charset);
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401"); // Do as if you'rusing Firefox 3.6.3
urlResponse = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader( new InputStreamReader(urlResponse) );
While accesing the page i'm getting this issue
org.apache.sling.auth.core.impl.SlingAuthenticator getAnonymousResolver: `Anonymous access not allowed by configuration - requesting credentials`
I'm logged in as an admin and whenever i'm directly hitting this urlfrom browser it is working properly bt while accessing it thriugh my code i'm getting this error.
any suggestion ?
If you are trying to call an url on an author instance, the following method I use in one of my projects might help (using apache commons HttpClient):
private InputStream getContent(final String url)
HttpClient httpClient = new HttpClient();
httpClient.getParams().setAuthenticationPreemptive(true);
httpClient.getState().setCredentials(new AuthScope(null, -1, null),
new UsernamePasswordCredentials("admin", "admin"));
try {
GetMethod get = new GetMethod(url);
httpClient.executeMethod(get);
if (get.getStatusCode() == HttpStatus.SC_OK) {
return get.getResponseBodyAsStream();
} else {
LOGGER.error("HTTP Error: ", get.getStatusCode());
}
} catch (HttpException e) {
LOGGER.error("HttpException: ", e);
} catch (IOException e) {
LOGGER.error("IOException: ", e);
}
}
Though at it is using admin:admin it only works on a local dev instance, if you are on a productive environment, I wouldn't put the admin password in plaintext, even though it is onyl code...
You are mixing up sling credentials & http credentials. While you are logged in at the sling-repository the http session is not aware of any authentication informations!

Apache Abdera Client giving No credentials available for NTLM <any realm>#proxy.tcs.com:8080

I have seen many forum posts for this and tried several suggestions but still I am not able to solve this. The code works good at my home system, but behind the organization firewall it gives a exception message :
No credentials available for NTLM #proxy.tcs.com:8080
Here is the method which I am using
private static void UseAbdera() throws IOException
{
try
{
Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
client.setProxy("OrgProxyHost", 8080);
NTLMAuthenticatorClass authenticator = new NTLMAuthenticatorClass("username", "password");
Authenticator.setDefault(authenticator);
NTCredentials ntcr = new NTCredentials("username", "password", "greenhouse.lotus.com", "India.TCS.com");
client.addCredentials("https://greenhouse.lotus.com", null, null, ntcr);
ClientResponse resp = client.get("https://greenhouse.lotus.com/forums/atom/service");
org.apache.abdera.model.Document<org.apache.abdera.model.Service> service_doc = resp.getDocument();
service_doc.writeTo(System.out);
System.out.println("\n");
org.apache.abdera.model.Service service = service_doc.getRoot();
org.apache.abdera.model.Collection collection = service.getCollection("Forums Feed Collection", "My Topics");
String coll_uri = collection.getResolvedHref().toASCIIString();
org.apache.abdera.model.Entry entry = abdera.newEntry();
entry.setTitle("TEST REPLY !");
// Mark private
resp = client.post(coll_uri, entry);
switch (resp.getType())
{
case SUCCESS:
String location = resp.getLocation().toASCIIString();
System.out.println("New entry created at: " + location);
break;
default:
System.out.println("Error: " + resp.getStatusText());
}
} catch (URISyntaxException ex)
{
Logger.getLogger(IBMConnectionMessages_ForumPractice.class.getName()).log(Level.SEVERE, null, ex);
}
}
This is the exception log I get
org.apache.commons.httpclient.auth.AuthChallengeProcessor selectAuthScheme
INFO: ntlm authentication scheme selected
Jul 6, 2012 10:42:03 AM org.apache.commons.httpclient.HttpMethodDirector processProxyAuthChallenge
INFO: No credentials available for NTLM #orgProxyHost:8080
Exception in thread "main" java.lang.IllegalStateException
at org.apache.abdera.protocol.client.CommonsResponse.(CommonsResponse.java:44)
at org.apache.abdera.protocol.client.AbderaClient.execute(AbderaClient.java:692)
at org.apache.abdera.protocol.client.AbderaClient.get(AbderaClient.java:216)
at org.apache.abdera.protocol.client.AbderaClient.get(AbderaClient.java:404)
at IBMConnectionMessages_ForumPractice.UseAbdera(IBMConnectionMessages_ForumPractice.java:231)
at IBMConnectionMessages_ForumPractice.main(IBMConnectionMessages_ForumPractice.java:45)
Please help, I have spent half a day on it.
your proxy may need ntlm authentication, so provide your proxy authentication details as NTCredentials while setting proxy credentials.